|
本帖最后由 duanyudan123 于 2024-10-11 15:23 编辑
1、启明智显的4吋触摸屏(没有供电板)+openhasp来做的UI2、ac-dc电路自己画的板,附加语音功能。供电加语音一体。
3、使用esphome的语音助手组件
4、唤醒词使用的snowboy(本地)
5、语音转文字使用faster-whisper(本地cuda环境工作的)
6、文字转语音(云端的edgetts),piper本地部署讲中文好似洋人说的蹩脚中文,洋鬼子口音。edge比较省事不二选择
7、ha的对话代理+豆包的对话代理
以下演示的视频前半部分是ha自带的对话代理,后半部分是豆包模型的对话代理。没有配置意图的情况下都不尽如人意。
[media=x,500,375] https://b23.tv/SSdYzou[/media]
整个项目还是很繁琐的,而且还有很多地方都需要优化。如果论坛小伙伴有需要我将把所有资料放上来。
成本呢屏幕加语音板150-220左右。还有一个就是语音识别这个看自己想办法了。我是装了一个5000的电脑,实在不建议,反正有给gpu和没gpu是两回事,自己决断。有很多平替方案。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2024/10/11[media=x,500,375]【演示视频】 https://www.bilibili.com/video/B ... 39248b018c90a8495aa[/media]
1、1个触摸屏硬件:启明智显ZX3D95CE01S-R
2、1个喇叭:喇叭2030
3、1个天线:fpc天线
4、1个音频功放:MAX98357 I2S 音频放大器模块拆焊取器件节省成本
5、1个麦克风:INMP441全向麦克风模块拆焊取器件节省成本
6、1个AC-DC:AC-DC稳压/220转5V
7、1个ESP32-S3-N16R8
8、1个ASR-PRO-2M:ASR PRO语音识别模块顺带捎上2块得麦克风
9、1个86底盒:86中控屏幕智能开关底座
10、语音+电源+ASR-PRO缝合板(对插和缝合ASR-PRO未完成希望有人补充优化实在画不动了):
esp32语音版 AC-DC.zip
(586.64 KB, 下载次数: 0)
11、马蹄接线柱(我是从其它开关拆的这个需要自己适配)
12、连接线若干(如果有人优化对插则不需要)
以上是全部硬件需要自己焊接打板(最好能有人优化一下板子传上来)---------------------------------------------------------------------------------------------------------------------------------
软件部分:
openhasp:openHASP选择PanleeZW3D95CE01S-TR
界面UI:
{"page":1,"id":1,"obj":"img","x": 160,"y": 10,"w": 320,"h": 320,"bg_opa":255,"src":"L:/bj1.png"}
{"page":1,"comment":"------------------主页标签"}
{"page": 1,"id": 10,"obj": "label","x": 5,"y": 10,"w": 150,"h": 150,"bg_opa":255,"text":"\n\n\n\n主页","text_font":"hmf25","align":"center","bg_color":"#6CEBED","radius":5,"value_str":"\uE2DC","value_font":"60","value_align":"0","value_color":"#FFFD55","action": {"down": "p1b60.val=0"}}
{"page":1,"comment":"------------------温控标签"}
{"page": 1,"id": 20,"obj": "label","x": 5,"y": 165,"w": 150,"h": 150,"bg_opa":255,"text":"\n\n\n\n温控","text_font":"hmf25","align":"center","bg_color":"#77FF63","radius":5,"value_str":"\uE01B","value_font":"60","value_align":"0","value_color":"#FFFD55","action": {"down": "p1b60.val=1"}}
{"page": 1,"id": 21,"obj": "btn","x": 95,"y":5,"w": 50,"h": 50,"bg_opa":70,"parentid":20,"radius":30,"text":"\uE425","text_font":40,"align":"center","bg_grad_dir":0,"border_side":0,"bg_color":"#418C36","text_color":"#969696"}
{"page":1,"comment":"------------------灯光标签1"}
{"page": 1,"id": 30,"obj": "label","x": 5,"y":320,"w": 150,"h": 150,"bg_opa":255,"text":"\n\n\n\n灯光1","text_font":"hmf25","align":"center","bg_color":"#409BE3","radius":5,"value_str":"\uE6E8","value_font":"60","value_align":"0","value_color":"#FFFD55"}
{"page": 1,"id": 31,"obj": "btn","x": 95,"y":5,"w": 50,"h": 50,"bg_opa":70,"parentid":30,"radius":30,"text":"\uE1D9","text_font":40,"align":"center","bg_grad_dir":0,"border_side":0,"bg_color":"#418C36","text_color":"#FFFFFF","action": {"down": "p1b60.val=2"}}
{"page":1,"comment":"------------------灯光标签2"}
{"page": 1,"id": 40,"obj": "label","x": 160,"y": 320,"w": 155,"h": 150,"bg_opa":255,"text":"\n\n\n\n灯光2","text_font":"hmf25","align":"center","bg_color":"#E6817E","radius":5,"value_str":"\uE6E8","value_font":"60","value_align":"0","value_color":"#FFFD55"}
{"page": 1,"id": 41,"obj": "btn","x": 95,"y":5,"w": 50,"h": 50,"bg_opa":70,"parentid":40,"radius":30,"text":"\uE1D9","text_font":40,"align":"center","bg_grad_dir":0,"border_side":0,"bg_color":"#418C36","text_color":"#FFFFFF","action": {"down": "p1b60.val=3"}}
{"page":1,"comment":"------------------灯光标签3"}
{"page": 1,"id": 50,"obj": "label","x": 320,"y": 320,"w": 155,"h": 150,"bg_opa":255,"text":"\n\n\n\n灯光3","text_font":"hmf25","align":"center","bg_color":"#8A1E94","radius":5,"value_str":"\uE6E8","value_font":"60","value_align":"0","value_color":"#FFFD55"}
{"page": 1,"id": 51,"obj": "btn","x": 95,"y":5,"w": 50,"h": 50,"bg_opa":70,"parentid":50,"radius":30,"text":"\uE1D9","text_font":40,"align":"center","bg_grad_dir":0,"border_side":0,"bg_color":"#418C36","text_color":"#FFFFFF","action": {"down": "p1b60.val=4"}}
{"page":1,"comment":"------------------选项卡主体"}
{"page":1,"id":60,"obj":"tabview","btn_pos":0,"x":160,"y":10,"w":325,"h":315,"bg_opa":0,"border_opa":0,"bg_color":"#E6817E","bg_grad_dir":0,"hidden":0}
{"page":1,"id":70,"obj":"tab","parentid":60,"text":"Tab 0"}
{"page":1,"id":80,"obj":"tab","parentid":60,"text":"Tab 1"}
{"page":1,"id":90,"obj":"tab","parentid":60,"text":"Tab 2"}
{"page":1,"id":100,"obj":"tab","parentid":60,"text":"Tab 3"}
{"page":1,"id":110,"obj":"tab","parentid":60,"text":"Tab 4"}
{"page":1,"comment":"------------------选项卡主页"}
{"page":1,"id":120,"obj":"label","x":0,"y":0,"w":315,"h":150,"parentid":70,"bg_opa":0,"template":"%H:%M","text_font":120,"align":"center","hidden":0}
{"page":1,"id":130,"obj":"label","x":0,"y":155,"w":150,"h":150,"parentid":70,"bg_opa":0,"text":"\uE596","text_font":120,"align":"center","hidden":0}
{"page":1,"id":140,"obj":"label","x":155,"y":155,"w":160,"h":80,"parentid":70,"bg_opa":0,"text":"20.9°C","text_font":60,"align":"center","hidden":0}
{"page":1,"id":150,"obj":"label","x":155,"y":235,"w":160,"h":70,"parentid":70,"bg_opa":0,"text":"多云 30/24°C\n10月19日星期四\n八月十七","text_font":"hmf20","align":"center","hidden":0}
{"page":1,"comment":"------------------选项卡温控页"}
{"page":1,"id":160,"obj":"gauge","x":65,"y":25,"w":200,"h":200,"parentid":80,"min":170,"max":300,"val":0,"format":1,"critical_value":301,"label_count":14,"line_count":27,"border_width":0,"pad_top":2,"pad_bottom":2,"pad_left":2,"pad_right":2,"value_str":"°C","value_ofs_y":55,"value_font":30,"bg_opa":0,"line_width10":5,"line_rounded10":1,"line_color":"#348feb","line_color60":"#348feb","scale_grad_color":"#eb4934","scale_grad_color60":"#eb4934","scale_end_color60":"#eb4934","pad_inner":16,"text_font":20,"hidden":0}
{"page":1,"id":170,"obj":"arc","x":40,"y":0,"w":250,"h":250,"parentid":80,"min":17,"max":30,"val":26,"border_side":0,"type":0,"rotation":0,"start_angle":135,"end_angle":45,"adjustable":"true","line_width":21,"line_width10":21,"line_color10":"#34bdeb","bg_opa":0,"pad_top20":5,"pad_bottom20":5,"pad_left20":5,"pad_right20":5,"pad_top":5,"pad_bottom":5,"pad_left":5,"pad_right":5,"hidden":0}
{"page":1,"id":180,"obj":"btn","x":0,"y":235,"w":70,"h":70,"radius":5,"parentid":80,"bg_opa":255,"bg_grad_dir":0,"bg_color":"#52AFFA","bg_color02":"#C2BC29","border_side":0,"text":"\uE717","text_font":50}
{"page":1,"id":190,"obj":"btn","x":82,"y":235,"w":70,"h":70,"radius":5,"parentid":80,"bg_opa":255,"bg_grad_dir":0,"bg_color":"#FF8C26","bg_color02":"#C2BC29","border_side":0,"text":"\uE238","text_font":50}
{"page":1,"id":200,"obj":"btn","x":165,"y":255,"w":45,"h":50,"radius":5,"parentid":80,"bg_opa":255,"bg_grad_dir":0,"bg_color":"#006B04","bg_color02":"#C2BC29","border_side":0,"text":"\uE210","text_font":25}
{"page":1,"id":210,"obj":"btn","x":215,"y":245,"w":45,"h":60,"radius":5,"parentid":80,"bg_opa":255,"bg_grad_dir":0,"bg_color":"#00AD07","bg_color02":"#C2BC29","border_side":0,"text":"\uE210","text_font":35}
{"page":1,"id":220,"obj":"btn","x":265,"y":235,"w":45,"h":70,"radius":5,"parentid":80,"bg_opa":255,"bg_grad_dir":0,"bg_color":"#00FF0B","bg_color02":"#C2BC29","border_side":0,"text":"\uE210","text_font":45}
{"page":1,"comment":"------------------选项卡灯光1"}
{"page":1,"id":230,"obj":"slider","x":60,"y":20,"w":70,"h":230,"parentid":90,"min":0,"max":255,"radius":15,"bg_opa":255,"bg_color":"#6CEBED","bg_grad_dir":0,"bg_opa20":0,"border_side":0,"border_side20":0,"bg_color10":"#DEDEDE","bg_grad_dir10":0,"bg_opa10":255,"hidden":0,"val":50}
{"page":1,"id":231,"obj":"slider","x":200,"y":20,"w":70,"h":230,"parentid":90,"min":2700,"max":6500,"radius":15,"bg_opa":255,"bg_color":"#DEDEDE","bg_grad_color":"#FFA500" ,"bg_grad_dir":1,"bg_grad_stop":350,"bg_opa20":255,"bg_grad_dir10":0,"bg_opa10":0,"border_side10":0,"bg_color20":"#FFFFFF","radius20":50,"bg_grad_dir20":0,"hidden":0,"val":4500}
{"page":1,"comment":"------------------选项卡灯光2"}
{"page":1,"id":232,"obj":"slider","x":60,"y":20,"w":70,"h":230,"parentid":100,"min":0,"max":255,"radius":15,"bg_opa":255,"bg_color":"#E6817E","bg_grad_dir":0,"bg_opa20":0,"border_side":0,"border_side20":0,"bg_color10":"#DEDEDE","bg_grad_dir10":0,"bg_opa10":255,"hidden":0,"val":50}
{"page":1,"id":233,"obj":"slider","x":200,"y":20,"w":70,"h":230,"parentid":100,"min":2700,"max":6500,"radius":15,"bg_opa":255,"bg_color":"#DEDEDE","bg_grad_color":"#FFA500" ,"bg_grad_dir":1,"bg_grad_stop":350,"bg_opa20":255,"bg_grad_dir10":0,"bg_opa10":0,"border_side10":0,"bg_color20":"#FFFFFF","radius20":50,"bg_grad_dir20":0,"hidden":0,"val":4500}
{"page":1,"comment":"------------------选项卡灯光3"}
{"page":1,"id":234,"obj":"slider","x":60,"y":20,"w":70,"h":230,"parentid":110,"min":0,"max":255,"radius":15,"bg_opa":255,"bg_color":"#8A1E94","bg_grad_dir":0,"bg_opa20":0,"border_side":0,"border_side20":0,"bg_color10":"#DEDEDE","bg_grad_dir10":0,"bg_opa10":255,"hidden":0,"val":50}
{"page":1,"id":235,"obj":"slider","x":200,"y":20,"w":70,"h":230,"parentid":110,"min":2700,"max":6500,"radius":15,"bg_opa":255,"bg_color":"#DEDEDE","bg_grad_color":"#FFA500" ,"bg_grad_dir":1,"bg_grad_stop":350,"bg_opa20":255,"bg_grad_dir10":0,"bg_opa10":0,"border_side10":0,"bg_color20":"#FFFFFF","radius20":50,"bg_grad_dir20":0,"hidden":0,"val":4500}
{"page":1,"comment":"------------------语音助手对话标签"}
{"page":1,"id":236,"obj":"label","x":0,"y":400,"w":480,"h":80,"bg_opa":200,"radius":10,"align":"left","mode":"dots","text":"你好","text_font":"hmf30","text_color":"#000000","hidden":1}
openhasp集成:openhasp集成HA配置文件增加如下(configuration.yaml)
openhasp: !include_dir_merge_named openhasp_configs/
config下新建文件openhasp_configs/plate01.yaml
plate01.yaml配置如下:
plate01:
objects:
#天气图标
- obj: "p1b130"
properties:
"text": >
{% if is_state('你的天气实体','sunny') -%}
{{ "\uE5A8" }}
{% elif is_state('你的天气实体','partlycloudy') -%}
{{ "\uE595" }}
{% elif is_state('你的天气实体','cloudy') -%}
{{ "\uE590" }}
{% elif is_state('你的天气实体','rainy') -%}
{{ "\uE597" }}
{% elif is_state('你的天气实体','lightningrainy') -%}
{{ "\uE67E" }}
{% elif is_state('你的天气实体','hail') -%}
{{ "\uE592" }}
{% elif is_state('你的天气实体','snowyrainy') -%}
{{ "\uE67F" }}
{% elif is_state('你的天气实体','pouring') -%}
{{ "\uE596" }}
{% elif is_state('你的天气实体','snowy') -%}
{{ "\uE598" }}
{% elif is_state('你的天气实体','fog') -%}
{{ "\uE591" }}
{% elif is_state('你的天气实体','exceptional') -%}
{{ "\uE595" }}
{% elif is_state('你的天气实体','windy') -%}
{{ "\uE59D" }}
{% endif %}
#室外温度
- obj: "p1b140"
properties:
"text": "{{ state_attr('你的天气实体','temperature') }}°C"
#最高温度&日期&农历
- obj: "p1b150"
properties:
"text": "{{ state_attr('你的天气实体','condition_desc') }} {{ state_attr('你的天气实体','temphigh') | int }}/{{ state_attr('你的天气实体','templow') | int }}°C\n{{ state_attr('sensor.holiday','今天')[5:] }}{{ state_attr('sensor.holiday','星期') }}\n{{ state_attr('sensor.holiday','农历')[5:] }}"
#主卧空调电源开关
- obj: "p1b21"
properties:
"val": '{{ 1 if states("你的空调实体") == "on" else 0 }}'
"text_color": >
{% if is_state('你的空调实体', 'cool') %}
{{ "#346beb" }}
{%-elif is_state('你的空调实体', 'heat') %}
{{ "#eb3434" }}
{%-elif is_state('你的空调实体', 'auto') %}
{{ "#FF7F27" }}
{%-else %}
{{ "#9f96b0" }}
{% endif %}
event:
"up":
- service: homeassistant.toggle
entity_id: "你的空调实体"
#温控标签
- obj: "p1b20"
properties:
"value_color": >
{% if is_state('你的空调实体', 'cool') %}
{{ "#346beb" }}
{%-elif is_state('你的空调实体', 'heat') %}
{{ "#eb3434" }}
{%-elif is_state('你的空调实体', 'auto') %}
{{ "#FF7F27" }}
{%-else %}
{{ "#9f96b0" }}
{% endif %}
#空调目标温度滑块
- obj: "p1b170"
properties:
"val": >
{% if state_attr('你的空调实体','temperature') is not none %}
{{ state_attr('你的空调实体','temperature')}}
{%- endif %}
"line_color1": >
{% if is_state('你的空调实体', 'cool') %}
{{ "#346beb" }}
{%-elif is_state('你的空调实体', 'heat') %}
{{ "#eb3434" }}
{%-elif is_state('你的空调实体', 'auto') %}
{{ "#FF7F27" }}
{%-else %}
{{ "#9f96b0" }}
{% endif %}
event:
"changed":
- service: climate.set_temperature
target:
entity_id: 你的空调实体
data:
temperature: "{{ val }}"
"up":
- service: climate.set_temperature
target:
entity_id: 你的空调实体
data:
temperature: "{{ val }}"
#空调室温仪表
- obj: "p1b160"
properties:
"val": >
{% if not (is_state('你的温湿度实体','unavailable') or is_state('你的温湿度实体','unknown')) %}
{{ states('你的温湿度实体') | int * 10 }}
{%- endif %}
#空调模式按钮
- obj: "p1b180"
properties:
"text_color": '{{ "#346beb" if states("你的空调实体") == "cool" else "#9f96b0" }}'
event:
"down":
- service: climate.set_hvac_mode
target:
entity_id: 你的空调实体
data:
hvac_mode: cool
- obj: "p1b190"
properties:
"text_color": '{{ "#346beb" if states("你的空调实体") == "heat" else "#9f96b0" }}'
event:
"down":
- service: climate.set_hvac_mode
target:
entity_id: 你的空调实体
data:
hvac_mode: heat
#空调风速按钮
- obj: "p1b200"
properties:
"text_color": >
{% if state_attr('你的空调实体','fan_mode') == "low" %}
{{ "#FFFFFF"}}
{%-else %}
{{ "#9f96b0" }}
{% endif %}
event:
"down":
- service: climate.set_fan_mode
target:
entity_id: 你的空调实体
data:
fan_mode: low
- obj: "p1b210"
properties:
"text_color": >
{% if state_attr('你的空调实体','fan_mode') == "medium" %}
{{ "#FFFFFF"}}
{%-else %}
{{ "#9f96b0" }}
{% endif %}
event:
"down":
- service: climate.set_fan_mode
target:
entity_id: 你的空调实体
data:
fan_mode: medium
- obj: "p1b220"
properties:
"text_color": >
{% if state_attr('你的空调实体','fan_mode') == "high" %}
{{ "#FFFFFF"}}
{%-else %}
{{ "#9f96b0" }}
{% endif %}
event:
"down":
- service: climate.set_fan_mode
target:
entity_id: 你的空调实体
data:
fan_mode: high
#灯光1标签
- obj: "p1b30"
properties:
"value_color": '{{ "#F09B59" if states("你的灯光实体1") == "on" else "#9f96b0" }}'
event:
"down":
- service: light.toggle
target:
entity_id: 你的灯光实体1
#灯光1亮度滑块
- obj: "p1b230"
properties:
"val": "{{ state_attr('你的灯光实体1', 'brightness') if state_attr('你的灯光实体1', 'brightness') != None else 0 }}"
event:
"changed":
- service: light.turn_on
data:
entity_id: 你的灯光实体1
brightness: "{{ val }}"
"up":
- service: light.turn_on
data:
entity_id: 你的灯光实体1
brightness: "{{ val }}"
#灯光1色温滑块
- obj: "p1b231"
properties:
"val": "{{ state_attr('你的灯光实体1', 'color_temp_kelvin') if state_attr('你的灯光实体1', 'color_temp_kelvin') != None else 0 }}"
event:
"changed":
- service: light.turn_on
data:
entity_id: 你的灯光实体1
color_temp_kelvin: "{{ val }}"
"up":
- service: light.turn_on
data:
entity_id: 你的灯光实体1
color_temp_kelvin: "{{ val }}"
#灯光2标签
- obj: "p1b40"
properties:
"value_color": '{{ "#F09B59" if states("你的灯光实体2") == "on" else "#9f96b0" }}'
event:
"down":
- service: light.toggle
target:
entity_id: 你的灯光实体2
#灯光2亮度滑块
- obj: "p1b232"
properties:
"val": "{{ state_attr('你的灯光实体2', 'brightness') if state_attr('你的灯光实体2', 'brightness') != None else 0 }}"
event:
"changed":
- service: light.turn_on
data:
entity_id: 你的灯光实体2
brightness: "{{ val }}"
"up":
- service: light.turn_on
data:
entity_id: 你的灯光实体2
brightness: "{{ val }}"
#灯光2色温滑块
- obj: "p1b233"
properties:
"val": "{{ state_attr('你的灯光实体2', 'color_temp_kelvin') if state_attr('你的灯光实体2', 'color_temp_kelvin') != None else 0 }}"
event:
"changed":
- service: light.turn_on
data:
entity_id: 你的灯光实体2
color_temp_kelvin: "{{ val }}"
"up":
- service: light.turn_on
data:
entity_id: 你的灯光实体2
color_temp_kelvin: "{{ val }}"
#灯光3标签
- obj: "p1b50"
properties:
"value_color": '{{ "#F09B59" if states("你的灯光实体3") == "on" else "#9f96b0" }}'
event:
"down":
- service: light.toggle
target:
entity_id: 你的灯光实体3
#灯光3亮度滑块
- obj: "p1b234"
properties:
"val": "{{ state_attr('你的灯光实体3', 'brightness') if state_attr('你的灯光实体3', 'brightness') != None else 0 }}"
event:
"changed":
- service: light.turn_on
data:
entity_id: 你的灯光实体3
brightness: "{{ val }}"
"up":
- service: light.turn_on
data:
entity_id: 你的灯光实体3
brightness: "{{ val }}"
#灯光3色温滑块
- obj: "p1b235"
properties:
"val": "{{ state_attr('你的灯光实体3', 'color_temp_kelvin') if state_attr('你的灯光实体3', 'color_temp_kelvin') != None else 0 }}"
event:
"changed":
- service: light.turn_on
data:
entity_id: 你的灯光实体3
color_temp_kelvin: "{{ val }}"
"up":
- service: light.turn_on
data:
entity_id: 你的灯光实体3
color_temp_kelvin: "{{ val }}"
#对话内容
- obj: "p1b236"
properties:
"hidden": '{{ 1 if states("你的语音助手实体") == "idle" else 0 }}'
"text": "{{states('sensor.plate02')}}"
语音助手配置:
substitutions:
voice_assist_idle_phase_id: '1'
voice_assist_listening_phase_id: '2'
voice_assist_thinking_phase_id: '3'
voice_assist_replying_phase_id: '4'
voice_assist_not_ready_phase_id: '10'
voice_assist_error_phase_id: '11'
voice_assist_muted_phase_id: '12'
esphome:
name: 非中文名字
friendly_name: 非中文名字
board_build.flash_mode: dio
psram:
mode: octal
speed: 80MHz
esp32:
board: esp32-s3-devkitc-1
flash_size: 16MB
framework:
type: esp-idf
sdkconfig_options:
CONFIG_ESP32_S3_BOX_BOARD: "y"
CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM: "16"
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM: "512"
CONFIG_TCPIP_RECVMBOX_SIZE: "512"
CONFIG_TCP_SND_BUF_DEFAULT: "65535"
CONFIG_TCP_WND_DEFAULT: "512000"
CONFIG_TCP_RECVMBOX_SIZE: "512"
logger:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
api:
encryption:
key: "12345"
ota:
password: "1234"
platform: esphome
esp32_ble:
enable_on_boot: false
button:
- platform: restart
name: "Restart"
id: but_rest
external_components:
- source:
type: local
path: mycomponents
# ref: dev-next
components: [ adf_pipeline, i2s_audio ]
# refresh: 0s
#上边是两个esphome外部组件
adf_pipeline:
- platform: i2s_audio
type: audio_out
id: adf_spk
i2s_audio_id: i2s_out
i2s_dout_pin: GPIO12
- platform: i2s_audio
type: audio_in
id: adf_mic
i2s_audio_id: i2s_in
i2s_din_pin: GPIO4
channel: left
sample_rate: 16000
bits_per_sample: 16bit
pdm: false
microphone:
- platform: adf_pipeline
id: adf_microphone
gain_log2: 3
keep_pipeline_alive: false
pipeline:
- adf_mic
- self
i2s_audio:
- id: i2s_in
i2s_lrclk_pin: GPIO01
i2s_bclk_pin: GPIO02
- id: i2s_out
i2s_lrclk_pin: GPIO15
i2s_bclk_pin: GPIO13
media_player:
- platform: adf_pipeline
id: adf_media_player
name: Media player
keep_pipeline_alive: false
internal: false
pipeline:
- self
- adf_spk
voice_assistant:
id: va
microphone: adf_microphone
media_player: adf_media_player
use_wake_word: false
noise_suppression_level: 2 #4
auto_gain: 31dBFS # 31dBFS
volume_multiplier: 2 # 8.0
on_listening:
- lambda: id(voice_assistant_phase) = ${voice_assist_listening_phase_id};
- text_sensor.template.publish:
id: text_request
state: "。。。"
- text_sensor.template.publish:
id: text_response
state: "。。。"
on_stt_vad_end:
- lambda: id(voice_assistant_phase) = ${voice_assist_thinking_phase_id};
on_stt_end:
- text_sensor.template.publish:
id: text_request
state: !lambda return x;
on_tts_start:
- lambda: id(voice_assistant_phase) = ${voice_assist_replying_phase_id};
- text_sensor.template.publish:
id: text_response
state: !lambda return x;
on_end:
- lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id};
globals:
- id: init_in_progress
type: bool
restore_value: no
initial_value: 'true'
- id: voice_assistant_phase
type: int
restore_value: no
initial_value: ${voice_assist_not_ready_phase_id}
text_sensor:
- id: text_request
platform: template
name: 对话内容
on_value:
lambda: |-
if(id(text_request).state.length()>100) {
std::string name = id(text_request).state.c_str();
std::string truncated = esphome::str_truncate(name.c_str(),99);
id(text_request).state = (truncated+"...").c_str();
}
- id: text_response
platform: template
name: 对话内容
on_value:
lambda: |-
if(id(text_response).state.length()>100) {
std::string name = id(text_response).state.c_str();
std::string truncated = esphome::str_truncate(name.c_str(),99);
id(text_response).state = (truncated+"...").c_str();
}
binary_sensor:
- platform: gpio
name: Click_to_Converse
id: Click_to_Converse
pin:
number: 21
on_press:
- homeassistant.service:
service: media_player.play_media
data:
entity_id: media_player.你的媒体播放器实体
media_content_id: "media-source://media_source/local/wozai.mp3"
media_content_type: music
- if:
condition:
- voice_assistant.is_running
then:
- voice_assistant.stop:
else:
- delay: 800ms
- voice_assistant.start:
ASR-PRO代替唤醒词(这个模块识别很好)接21gpio帮助一键通唤醒ASR-PRO不需要讲话:
语音转文字:官方推荐的whisper需要显卡才能发挥,论坛还有国内的方案没有测试硬件需求大家可以论坛搜一下
对话代理:官方的必须一个字不能错。qwen2.5需要显卡才能用。论坛内有白嫖国内AI服务商的教程。或者用谷歌和GPT
文字转语音:edgeTTS免费速度还可以。其它tts需要显卡可以自定义音色比如最近比较火的雷布斯的音色,不过没啥用!
以上的难点在于组装和拆焊还有焊接,那位坛友拿走优化一下改成对插基本没有什么难度。
|
评分
-
查看全部评分
|