homeassistant 2025.7.0b0__py3-none-any.whl → 2025.7.0b2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- homeassistant/components/aemet/sensor.py +1 -1
- homeassistant/components/airq/coordinator.py +2 -2
- homeassistant/components/alexa_devices/__init__.py +5 -2
- homeassistant/components/alexa_devices/notify.py +2 -0
- homeassistant/components/alexa_devices/quality_scale.yaml +1 -1
- homeassistant/components/alexa_devices/strings.json +11 -4
- homeassistant/components/alexa_devices/switch.py +2 -0
- homeassistant/components/alexa_devices/translations/bg.json +6 -4
- homeassistant/components/alexa_devices/translations/cs.json +12 -5
- homeassistant/components/alexa_devices/translations/de.json +14 -7
- homeassistant/components/alexa_devices/translations/el.json +12 -5
- homeassistant/components/alexa_devices/translations/en.json +12 -5
- homeassistant/components/alexa_devices/translations/es.json +12 -5
- homeassistant/components/alexa_devices/translations/et.json +12 -5
- homeassistant/components/alexa_devices/translations/ga.json +0 -6
- homeassistant/components/alexa_devices/translations/he.json +0 -4
- homeassistant/components/alexa_devices/translations/hu.json +0 -4
- homeassistant/components/alexa_devices/translations/id.json +1 -0
- homeassistant/components/alexa_devices/translations/lt.json +0 -4
- homeassistant/components/alexa_devices/translations/mk.json +12 -0
- homeassistant/components/alexa_devices/translations/nl.json +0 -4
- homeassistant/components/alexa_devices/translations/pl.json +0 -4
- homeassistant/components/alexa_devices/translations/pt.json +0 -4
- homeassistant/components/alexa_devices/translations/ru.json +4 -5
- homeassistant/components/alexa_devices/translations/sk.json +12 -5
- homeassistant/components/alexa_devices/translations/sv.json +17 -5
- homeassistant/components/alexa_devices/translations/tr.json +0 -4
- homeassistant/components/alexa_devices/translations/zh-Hans.json +27 -5
- homeassistant/components/alexa_devices/translations/zh-Hant.json +12 -5
- homeassistant/components/alexa_devices/utils.py +40 -0
- homeassistant/components/altruist/translations/id.json +11 -0
- homeassistant/components/anthropic/__init__.py +14 -1
- homeassistant/components/anthropic/translations/bg.json +21 -0
- homeassistant/components/anthropic/translations/ga.json +32 -1
- homeassistant/components/anthropic/translations/id.json +19 -0
- homeassistant/components/anthropic/translations/ru.json +30 -0
- homeassistant/components/backup/translations/de.json +1 -1
- homeassistant/components/buienradar/sensor.py +0 -1
- homeassistant/components/cambridge_audio/translations/sv.json +1 -1
- homeassistant/components/comelit/translations/de.json +1 -1
- homeassistant/components/counter/translations/sv.json +2 -2
- homeassistant/components/demo/translations/select.sv.json +2 -2
- homeassistant/components/derivative/translations/ga.json +20 -0
- homeassistant/components/derivative/translations/ru.json +3 -0
- homeassistant/components/devolo_home_control/translations/bg.json +6 -0
- homeassistant/components/devolo_home_control/translations/id.json +5 -0
- homeassistant/components/devolo_home_control/translations/sv.json +10 -0
- homeassistant/components/devolo_home_control/translations/zh-Hans.json +10 -0
- homeassistant/components/dlink/manifest.json +1 -1
- homeassistant/components/ecovacs/translations/sv.json +1 -1
- homeassistant/components/enphase_envoy/translations/sv.json +5 -2
- homeassistant/components/ezviz/translations/bg.json +6 -0
- homeassistant/components/ezviz/translations/mk.json +13 -0
- homeassistant/components/ezviz/translations/sv.json +10 -0
- homeassistant/components/ezviz/translations/zh-Hans.json +10 -0
- homeassistant/components/fronius/translations/sv.json +2 -2
- homeassistant/components/frontend/manifest.json +1 -1
- homeassistant/components/goodwe/translations/sv.json +5 -5
- homeassistant/components/google_generative_ai_conversation/__init__.py +21 -0
- homeassistant/components/google_generative_ai_conversation/config_flow.py +72 -36
- homeassistant/components/google_generative_ai_conversation/const.py +15 -2
- homeassistant/components/google_generative_ai_conversation/diagnostics.py +1 -0
- homeassistant/components/google_generative_ai_conversation/entity.py +7 -2
- homeassistant/components/google_generative_ai_conversation/helpers.py +73 -0
- homeassistant/components/google_generative_ai_conversation/strings.json +28 -1
- homeassistant/components/google_generative_ai_conversation/translations/bg.json +19 -0
- homeassistant/components/google_generative_ai_conversation/translations/cs.json +28 -0
- homeassistant/components/google_generative_ai_conversation/translations/de.json +28 -0
- homeassistant/components/google_generative_ai_conversation/translations/el.json +28 -0
- homeassistant/components/google_generative_ai_conversation/translations/en.json +28 -0
- homeassistant/components/google_generative_ai_conversation/translations/es.json +28 -0
- homeassistant/components/google_generative_ai_conversation/translations/et.json +28 -0
- homeassistant/components/google_generative_ai_conversation/translations/ga.json +9 -0
- homeassistant/components/google_generative_ai_conversation/translations/id.json +30 -0
- homeassistant/components/google_generative_ai_conversation/translations/mk.json +11 -0
- homeassistant/components/google_generative_ai_conversation/translations/ru.json +67 -0
- homeassistant/components/google_generative_ai_conversation/translations/sk.json +28 -0
- homeassistant/components/google_generative_ai_conversation/translations/sv.json +23 -0
- homeassistant/components/google_generative_ai_conversation/translations/zh-Hans.json +28 -0
- homeassistant/components/google_generative_ai_conversation/translations/zh-Hant.json +28 -0
- homeassistant/components/google_generative_ai_conversation/tts.py +48 -106
- homeassistant/components/group/translations/el.json +18 -18
- homeassistant/components/habitica/const.py +1 -1
- homeassistant/components/harmony/translations/select.sv.json +1 -1
- homeassistant/components/harmony/translations/sv.json +1 -1
- homeassistant/components/homeassistant_hardware/firmware_config_flow.py +89 -7
- homeassistant/components/homeassistant_hardware/strings.json +2 -1
- homeassistant/components/homeassistant_hardware/translations/de.json +1 -0
- homeassistant/components/homeassistant_hardware/translations/en-GB.json +1 -0
- homeassistant/components/homeassistant_hardware/translations/en.json +1 -0
- homeassistant/components/homeassistant_hardware/translations/ga.json +9 -0
- homeassistant/components/homeassistant_hardware/translations/mk.json +9 -0
- homeassistant/components/homeassistant_sky_connect/config_flow.py +1 -1
- homeassistant/components/homeassistant_sky_connect/strings.json +4 -2
- homeassistant/components/homeassistant_sky_connect/translations/de.json +2 -0
- homeassistant/components/homeassistant_sky_connect/translations/en-GB.json +2 -0
- homeassistant/components/homeassistant_sky_connect/translations/en.json +2 -0
- homeassistant/components/homeassistant_sky_connect/translations/ga.json +10 -0
- homeassistant/components/homeassistant_sky_connect/translations/mk.json +7 -0
- homeassistant/components/homeassistant_yellow/strings.json +2 -1
- homeassistant/components/homeassistant_yellow/translations/bg.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/cs.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/de.json +1 -0
- homeassistant/components/homeassistant_yellow/translations/el.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/en-GB.json +2 -1
- homeassistant/components/homeassistant_yellow/translations/en.json +2 -1
- homeassistant/components/homeassistant_yellow/translations/es.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/et.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/fr.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/ga.json +5 -0
- homeassistant/components/homeassistant_yellow/translations/he.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/hu.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/id.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/it.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/ja.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/lt.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/pt.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/ru.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/sk.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/sv.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/tr.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/zh-Hans.json +0 -1
- homeassistant/components/homeassistant_yellow/translations/zh-Hant.json +0 -1
- homeassistant/components/homewizard/translations/sv.json +3 -1
- homeassistant/components/http/auth.py +1 -1
- homeassistant/components/image/__init__.py +34 -3
- homeassistant/components/input_number/translations/sv.json +2 -2
- homeassistant/components/input_select/translations/sv.json +6 -6
- homeassistant/components/input_text/translations/sv.json +1 -1
- homeassistant/components/iron_os/manifest.json +1 -1
- homeassistant/components/iron_os/translations/sv.json +1 -1
- homeassistant/components/keenetic_ndms2/translations/id.json +3 -0
- homeassistant/components/lamarzocco/entity.py +19 -1
- homeassistant/components/lamarzocco/number.py +0 -4
- homeassistant/components/lamarzocco/sensor.py +2 -4
- homeassistant/components/lamarzocco/translations/sv.json +3 -3
- homeassistant/components/lametric/translations/sv.json +2 -2
- homeassistant/components/lametric/update.py +1 -1
- homeassistant/components/lg_thinq/translations/sv.json +5 -5
- homeassistant/components/litterrobot/translations/bg.json +4 -0
- homeassistant/components/litterrobot/translations/ga.json +3 -0
- homeassistant/components/matter/translations/id.json +5 -0
- homeassistant/components/matter/vacuum.py +38 -26
- homeassistant/components/meater/__init__.py +5 -1
- homeassistant/components/meater/coordinator.py +4 -2
- homeassistant/components/media_source/local_source.py +21 -4
- homeassistant/components/minecraft_server/translations/sv.json +1 -1
- homeassistant/components/motioneye/translations/sv.json +1 -1
- homeassistant/components/mqtt/translations/bg.json +10 -0
- homeassistant/components/mqtt/translations/cs.json +19 -0
- homeassistant/components/mqtt/translations/el.json +21 -0
- homeassistant/components/mqtt/translations/fi.json +3 -0
- homeassistant/components/mqtt/translations/ga.json +25 -0
- homeassistant/components/mqtt/translations/mk.json +23 -0
- homeassistant/components/mqtt/translations/ru.json +1 -0
- homeassistant/components/mqtt/translations/sv.json +24 -0
- homeassistant/components/mqtt/translations/zh-Hans.json +26 -0
- homeassistant/components/mqtt/translations/zh-Hant.json +19 -0
- homeassistant/components/music_assistant/button.py +0 -6
- homeassistant/components/ntfy/translations/id.json +13 -0
- homeassistant/components/ntfy/translations/sv.json +1 -0
- homeassistant/components/number/translations/sv.json +2 -2
- homeassistant/components/nut/config_flow.py +4 -2
- homeassistant/components/ohme/translations/sv.json +1 -1
- homeassistant/components/ollama/__init__.py +8 -0
- homeassistant/components/ollama/const.py +2 -0
- homeassistant/components/ollama/translations/bg.json +19 -0
- homeassistant/components/ollama/translations/ga.json +31 -1
- homeassistant/components/ollama/translations/id.json +18 -0
- homeassistant/components/ollama/translations/mk.json +13 -1
- homeassistant/components/ollama/translations/sv.json +1 -0
- homeassistant/components/onewire/translations/sv.json +4 -4
- homeassistant/components/openai_conversation/__init__.py +8 -0
- homeassistant/components/openai_conversation/const.py +1 -1
- homeassistant/components/openai_conversation/conversation.py +1 -1
- homeassistant/components/openai_conversation/translations/bg.json +26 -0
- homeassistant/components/openai_conversation/translations/id.json +23 -0
- homeassistant/components/openai_conversation/translations/mk.json +44 -0
- homeassistant/components/openai_conversation/translations/sv.json +4 -0
- homeassistant/components/playstation_network/diagnostics.py +55 -0
- homeassistant/components/playstation_network/quality_scale.yaml +1 -1
- homeassistant/components/playstation_network/translations/bg.json +25 -1
- homeassistant/components/playstation_network/translations/es.json +1 -1
- homeassistant/components/playstation_network/translations/ga.json +31 -0
- homeassistant/components/playstation_network/translations/id.json +14 -0
- homeassistant/components/playstation_network/translations/mk.json +18 -0
- homeassistant/components/playstation_network/translations/pl.json +73 -0
- homeassistant/components/playstation_network/translations/sv.json +29 -0
- homeassistant/components/playstation_network/translations/zh-Hans.json +29 -0
- homeassistant/components/plugwise/translations/sv.json +2 -2
- homeassistant/components/qnap/translations/sv.json +1 -1
- homeassistant/components/random/translations/sv.json +4 -4
- homeassistant/components/remote_calendar/translations/fi.json +34 -0
- homeassistant/components/select/translations/sv.json +10 -10
- homeassistant/components/smarla/__init__.py +2 -2
- homeassistant/components/sonos/translations/bg.json +5 -0
- homeassistant/components/sonos/translations/cs.json +6 -0
- homeassistant/components/sonos/translations/el.json +6 -0
- homeassistant/components/sonos/translations/ga.json +8 -0
- homeassistant/components/sonos/translations/mk.json +10 -0
- homeassistant/components/sonos/translations/ru.json +6 -0
- homeassistant/components/sonos/translations/sv.json +6 -0
- homeassistant/components/sonos/translations/zh-Hans.json +9 -0
- homeassistant/components/sonos/translations/zh-Hant.json +6 -0
- homeassistant/components/subaru/strings.json +2 -2
- homeassistant/components/subaru/translations/ca.json +0 -1
- homeassistant/components/subaru/translations/cs.json +0 -2
- homeassistant/components/subaru/translations/de.json +2 -2
- homeassistant/components/subaru/translations/el.json +0 -2
- homeassistant/components/subaru/translations/en-GB.json +0 -2
- homeassistant/components/subaru/translations/en.json +2 -2
- homeassistant/components/subaru/translations/es.json +0 -2
- homeassistant/components/subaru/translations/et.json +0 -2
- homeassistant/components/subaru/translations/fi.json +0 -1
- homeassistant/components/subaru/translations/hu.json +0 -2
- homeassistant/components/subaru/translations/it.json +0 -1
- homeassistant/components/subaru/translations/ja.json +0 -1
- homeassistant/components/subaru/translations/ko.json +0 -1
- homeassistant/components/subaru/translations/lt.json +0 -2
- homeassistant/components/subaru/translations/pt-BR.json +0 -1
- homeassistant/components/subaru/translations/pt.json +0 -2
- homeassistant/components/subaru/translations/ru.json +0 -2
- homeassistant/components/subaru/translations/sk.json +0 -2
- homeassistant/components/subaru/translations/sv.json +0 -2
- homeassistant/components/subaru/translations/tr.json +0 -2
- homeassistant/components/subaru/translations/zh-Hans.json +0 -2
- homeassistant/components/subaru/translations/zh-Hant.json +0 -2
- homeassistant/components/switchbot/translations/bg.json +26 -0
- homeassistant/components/switchbot/translations/ga.json +33 -0
- homeassistant/components/switchbot/translations/id.json +19 -0
- homeassistant/components/switchbot/translations/mk.json +49 -0
- homeassistant/components/switchbot/translations/sv.json +54 -0
- homeassistant/components/switchbot/translations/zh-Hans.json +53 -0
- homeassistant/components/telegram_bot/__init__.py +20 -4
- homeassistant/components/telegram_bot/bot.py +33 -29
- homeassistant/components/telegram_bot/config_flow.py +66 -20
- homeassistant/components/telegram_bot/const.py +1 -1
- homeassistant/components/telegram_bot/strings.json +33 -10
- homeassistant/components/telegram_bot/translations/bg.json +0 -1
- homeassistant/components/telegram_bot/translations/cs.json +35 -12
- homeassistant/components/telegram_bot/translations/de.json +35 -12
- homeassistant/components/telegram_bot/translations/el.json +35 -12
- homeassistant/components/telegram_bot/translations/en-GB.json +6 -11
- homeassistant/components/telegram_bot/translations/en.json +35 -12
- homeassistant/components/telegram_bot/translations/es.json +35 -12
- homeassistant/components/telegram_bot/translations/et.json +34 -11
- homeassistant/components/telegram_bot/translations/fr.json +5 -12
- homeassistant/components/telegram_bot/translations/ga.json +5 -11
- homeassistant/components/telegram_bot/translations/he.json +3 -8
- homeassistant/components/telegram_bot/translations/hu.json +5 -12
- homeassistant/components/telegram_bot/translations/id.json +0 -5
- homeassistant/components/telegram_bot/translations/it.json +2 -5
- homeassistant/components/telegram_bot/translations/lt.json +5 -12
- homeassistant/components/telegram_bot/translations/mk.json +7 -5
- homeassistant/components/telegram_bot/translations/nl.json +5 -12
- homeassistant/components/telegram_bot/translations/pt.json +5 -12
- homeassistant/components/telegram_bot/translations/ru.json +12 -11
- homeassistant/components/telegram_bot/translations/sk.json +35 -12
- homeassistant/components/telegram_bot/translations/sv.json +28 -12
- homeassistant/components/telegram_bot/translations/tr.json +5 -12
- homeassistant/components/telegram_bot/translations/zh-Hans.json +35 -12
- homeassistant/components/telegram_bot/translations/zh-Hant.json +35 -12
- homeassistant/components/template/translations/sv.json +5 -5
- homeassistant/components/text/translations/sv.json +1 -1
- homeassistant/components/tilt_pi/translations/id.json +11 -0
- homeassistant/components/tts/__init__.py +15 -0
- homeassistant/components/unifiprotect/translations/zh-Hans.json +3 -3
- homeassistant/components/utility_meter/translations/sv.json +9 -9
- homeassistant/components/vegehub/translations/bg.json +2 -0
- homeassistant/components/vegehub/translations/id.json +11 -0
- homeassistant/components/vegehub/translations/sv.json +2 -1
- homeassistant/components/vicare/translations/sv.json +2 -2
- homeassistant/components/whirlpool/translations/sv.json +12 -12
- homeassistant/components/wyoming/translations/sv.json +2 -2
- homeassistant/components/zha/translations/bg.json +23 -0
- homeassistant/components/zha/translations/el.json +10 -0
- homeassistant/components/zha/translations/ga.json +20 -0
- homeassistant/components/zha/translations/id.json +6 -0
- homeassistant/components/zha/translations/sv.json +23 -0
- homeassistant/components/zha/translations/zh-Hans.json +50 -0
- homeassistant/components/zwave_js/api.py +1 -1
- homeassistant/components/zwave_js/config_flow.py +15 -68
- homeassistant/components/zwave_js/manifest.json +1 -1
- homeassistant/components/zwave_js/strings.json +1 -5
- homeassistant/components/zwave_js/translations/bg.json +0 -3
- homeassistant/components/zwave_js/translations/cs.json +0 -5
- homeassistant/components/zwave_js/translations/de.json +1 -5
- homeassistant/components/zwave_js/translations/el.json +0 -5
- homeassistant/components/zwave_js/translations/en-GB.json +1 -5
- homeassistant/components/zwave_js/translations/en.json +1 -5
- homeassistant/components/zwave_js/translations/es.json +1 -5
- homeassistant/components/zwave_js/translations/et.json +0 -5
- homeassistant/components/zwave_js/translations/ga.json +0 -5
- homeassistant/components/zwave_js/translations/hu.json +0 -5
- homeassistant/components/zwave_js/translations/lt.json +0 -5
- homeassistant/components/zwave_js/translations/mk.json +0 -5
- homeassistant/components/zwave_js/translations/pt.json +0 -5
- homeassistant/components/zwave_js/translations/ru.json +0 -5
- homeassistant/components/zwave_js/translations/sk.json +0 -5
- homeassistant/components/zwave_js/translations/sv.json +0 -5
- homeassistant/components/zwave_js/translations/zh-Hans.json +0 -5
- homeassistant/components/zwave_js/translations/zh-Hant.json +1 -5
- homeassistant/config_entries.py +6 -0
- homeassistant/const.py +1 -1
- homeassistant/package_constraints.txt +1 -1
- {homeassistant-2025.7.0b0.dist-info → homeassistant-2025.7.0b2.dist-info}/METADATA +1 -1
- {homeassistant-2025.7.0b0.dist-info → homeassistant-2025.7.0b2.dist-info}/RECORD +312 -294
- {homeassistant-2025.7.0b0.dist-info → homeassistant-2025.7.0b2.dist-info}/WHEEL +0 -0
- {homeassistant-2025.7.0b0.dist-info → homeassistant-2025.7.0b2.dist-info}/entry_points.txt +0 -0
- {homeassistant-2025.7.0b0.dist-info → homeassistant-2025.7.0b2.dist-info}/licenses/LICENSE.md +0 -0
- {homeassistant-2025.7.0b0.dist-info → homeassistant-2025.7.0b2.dist-info}/licenses/homeassistant/backports/LICENSE.Python +0 -0
- {homeassistant-2025.7.0b0.dist-info → homeassistant-2025.7.0b2.dist-info}/top_level.txt +0 -0
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
}
|
|
87
87
|
},
|
|
88
88
|
"relay_grid_action": {
|
|
89
|
-
"name": "\
|
|
89
|
+
"name": "Eln\u00e4ts\u00e5tg\u00e4rd",
|
|
90
90
|
"state": {
|
|
91
91
|
"none": "Ingen",
|
|
92
92
|
"not_powered": "Ej str\u00f6msatt",
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
}
|
|
96
96
|
},
|
|
97
97
|
"relay_microgrid_action": {
|
|
98
|
-
"name": "\
|
|
98
|
+
"name": "Mikron\u00e4ts\u00e5tg\u00e4rd",
|
|
99
99
|
"state": {
|
|
100
100
|
"none": "Ingen",
|
|
101
101
|
"not_powered": "Ej str\u00f6msatt",
|
|
@@ -195,6 +195,9 @@
|
|
|
195
195
|
"dc_voltage": {
|
|
196
196
|
"name": "DC-sp\u00e4nning"
|
|
197
197
|
},
|
|
198
|
+
"energy_produced": {
|
|
199
|
+
"name": "Energiproduktion sedan f\u00f6reg\u00e5ende rapport"
|
|
200
|
+
},
|
|
198
201
|
"energy_today": {
|
|
199
202
|
"name": "Elproduktion i dag"
|
|
200
203
|
},
|
|
@@ -82,6 +82,12 @@
|
|
|
82
82
|
"silent": "\u0411\u0435\u0437\u0448\u0443\u043c\u0435\u043d",
|
|
83
83
|
"soft": "\u041c\u0435\u043a"
|
|
84
84
|
}
|
|
85
|
+
},
|
|
86
|
+
"battery_camera_work_mode": {
|
|
87
|
+
"state": {
|
|
88
|
+
"custom": "\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u0438",
|
|
89
|
+
"plugged_in": "\u0412\u043a\u043b\u044e\u0447\u0435\u043d \u0432 \u043c\u0440\u0435\u0436\u0430\u0442\u0430"
|
|
90
|
+
}
|
|
85
91
|
}
|
|
86
92
|
},
|
|
87
93
|
"sensor": {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"entity": {
|
|
3
|
+
"select": {
|
|
4
|
+
"battery_camera_work_mode": {
|
|
5
|
+
"state": {
|
|
6
|
+
"custom": "\u041f\u0440\u0438\u043b\u0430\u0433\u043e\u0434\u0435\u043d\u043e",
|
|
7
|
+
"high_performance": "\u0412\u0438\u0441\u043e\u043a\u0438 \u043f\u0435\u0440\u0444\u043e\u0440\u043c\u0430\u043d\u0441\u0438",
|
|
8
|
+
"plugged_in": "\u0412\u043a\u043b\u0443\u0447\u0435\u043d\u043e"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -95,6 +95,16 @@
|
|
|
95
95
|
"silent": "Tyst",
|
|
96
96
|
"soft": "Mjuk"
|
|
97
97
|
}
|
|
98
|
+
},
|
|
99
|
+
"battery_camera_work_mode": {
|
|
100
|
+
"name": "Arbetsl\u00e4ge f\u00f6r batteri",
|
|
101
|
+
"state": {
|
|
102
|
+
"custom": "Anpassad",
|
|
103
|
+
"high_performance": "H\u00f6g prestanda",
|
|
104
|
+
"plugged_in": "Inkopplad",
|
|
105
|
+
"power_save": "Str\u00f6msparl\u00e4ge",
|
|
106
|
+
"super_power_save": "Superstr\u00f6msparl\u00e4ge"
|
|
107
|
+
}
|
|
98
108
|
}
|
|
99
109
|
},
|
|
100
110
|
"sensor": {
|
|
@@ -95,6 +95,16 @@
|
|
|
95
95
|
"silent": "\u9759\u9ed8",
|
|
96
96
|
"soft": "\u67d4\u548c"
|
|
97
97
|
}
|
|
98
|
+
},
|
|
99
|
+
"battery_camera_work_mode": {
|
|
100
|
+
"name": "\u7535\u6c60\u5de5\u4f5c\u6a21\u5f0f",
|
|
101
|
+
"state": {
|
|
102
|
+
"custom": "\u5b9a\u5236",
|
|
103
|
+
"high_performance": "\u9ad8\u6027\u80fd",
|
|
104
|
+
"plugged_in": "\u5df2\u63d2\u5165",
|
|
105
|
+
"power_save": "\u7701\u7535",
|
|
106
|
+
"super_power_save": "\u8d85\u7ea7\u7701\u7535"
|
|
107
|
+
}
|
|
98
108
|
}
|
|
99
109
|
},
|
|
100
110
|
"sensor": {
|
|
@@ -374,10 +374,10 @@
|
|
|
374
374
|
"name": "DC-sp\u00e4nning"
|
|
375
375
|
},
|
|
376
376
|
"voltage_dc_maximum_cell": {
|
|
377
|
-
"name": "
|
|
377
|
+
"name": "H\u00f6gsta cellsp\u00e4nning"
|
|
378
378
|
},
|
|
379
379
|
"voltage_dc_minimum_cell": {
|
|
380
|
-
"name": "
|
|
380
|
+
"name": "L\u00e4gsta cellsp\u00e4nning"
|
|
381
381
|
},
|
|
382
382
|
"voltage_dc_mppt_no": {
|
|
383
383
|
"name": "DC-sp\u00e4nning {mppt_no}"
|
|
@@ -36,12 +36,12 @@
|
|
|
36
36
|
"name": "Driftl\u00e4ge f\u00f6r v\u00e4xelriktaren",
|
|
37
37
|
"state": {
|
|
38
38
|
"backup": "L\u00e4ge f\u00f6r s\u00e4kerhetskopiering",
|
|
39
|
-
"eco": "
|
|
40
|
-
"eco_charge": "
|
|
41
|
-
"eco_discharge": "
|
|
42
|
-
"general": "
|
|
39
|
+
"eco": "Eko-l\u00e4ge",
|
|
40
|
+
"eco_charge": "Eko-laddningsl\u00e4ge",
|
|
41
|
+
"eco_discharge": "Eko-urladdningsl\u00e4ge",
|
|
42
|
+
"general": "Generellt l\u00e4ge",
|
|
43
43
|
"off_grid": "\u00d6driftsl\u00e4ge",
|
|
44
|
-
"peak_shaving": "
|
|
44
|
+
"peak_shaving": "Topputj\u00e4mningsl\u00e4ge"
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import asyncio
|
|
6
6
|
import mimetypes
|
|
7
7
|
from pathlib import Path
|
|
8
|
+
from types import MappingProxyType
|
|
8
9
|
|
|
9
10
|
from google.genai import Client
|
|
10
11
|
from google.genai.errors import APIError, ClientError
|
|
@@ -36,10 +37,13 @@ from homeassistant.helpers.typing import ConfigType
|
|
|
36
37
|
|
|
37
38
|
from .const import (
|
|
38
39
|
CONF_PROMPT,
|
|
40
|
+
DEFAULT_TITLE,
|
|
41
|
+
DEFAULT_TTS_NAME,
|
|
39
42
|
DOMAIN,
|
|
40
43
|
FILE_POLLING_INTERVAL_SECONDS,
|
|
41
44
|
LOGGER,
|
|
42
45
|
RECOMMENDED_CHAT_MODEL,
|
|
46
|
+
RECOMMENDED_TTS_OPTIONS,
|
|
43
47
|
TIMEOUT_MILLIS,
|
|
44
48
|
)
|
|
45
49
|
|
|
@@ -242,6 +246,16 @@ async def async_migrate_integration(hass: HomeAssistant) -> None:
|
|
|
242
246
|
parent_entry = api_keys_entries[entry.data[CONF_API_KEY]]
|
|
243
247
|
|
|
244
248
|
hass.config_entries.async_add_subentry(parent_entry, subentry)
|
|
249
|
+
if use_existing:
|
|
250
|
+
hass.config_entries.async_add_subentry(
|
|
251
|
+
parent_entry,
|
|
252
|
+
ConfigSubentry(
|
|
253
|
+
data=MappingProxyType(RECOMMENDED_TTS_OPTIONS),
|
|
254
|
+
subentry_type="tts",
|
|
255
|
+
title=DEFAULT_TTS_NAME,
|
|
256
|
+
unique_id=None,
|
|
257
|
+
),
|
|
258
|
+
)
|
|
245
259
|
conversation_entity = entity_registry.async_get_entity_id(
|
|
246
260
|
"conversation",
|
|
247
261
|
DOMAIN,
|
|
@@ -270,12 +284,19 @@ async def async_migrate_integration(hass: HomeAssistant) -> None:
|
|
|
270
284
|
device.id,
|
|
271
285
|
remove_config_entry_id=entry.entry_id,
|
|
272
286
|
)
|
|
287
|
+
else:
|
|
288
|
+
device_registry.async_update_device(
|
|
289
|
+
device.id,
|
|
290
|
+
remove_config_entry_id=entry.entry_id,
|
|
291
|
+
remove_config_subentry_id=None,
|
|
292
|
+
)
|
|
273
293
|
|
|
274
294
|
if not use_existing:
|
|
275
295
|
await hass.config_entries.async_remove(entry.entry_id)
|
|
276
296
|
else:
|
|
277
297
|
hass.config_entries.async_update_entry(
|
|
278
298
|
entry,
|
|
299
|
+
title=DEFAULT_TITLE,
|
|
279
300
|
options={},
|
|
280
301
|
version=2,
|
|
281
302
|
)
|
|
@@ -47,13 +47,18 @@ from .const import (
|
|
|
47
47
|
CONF_TOP_P,
|
|
48
48
|
CONF_USE_GOOGLE_SEARCH_TOOL,
|
|
49
49
|
DEFAULT_CONVERSATION_NAME,
|
|
50
|
+
DEFAULT_TITLE,
|
|
51
|
+
DEFAULT_TTS_NAME,
|
|
50
52
|
DOMAIN,
|
|
51
53
|
RECOMMENDED_CHAT_MODEL,
|
|
54
|
+
RECOMMENDED_CONVERSATION_OPTIONS,
|
|
52
55
|
RECOMMENDED_HARM_BLOCK_THRESHOLD,
|
|
53
56
|
RECOMMENDED_MAX_TOKENS,
|
|
54
57
|
RECOMMENDED_TEMPERATURE,
|
|
55
58
|
RECOMMENDED_TOP_K,
|
|
56
59
|
RECOMMENDED_TOP_P,
|
|
60
|
+
RECOMMENDED_TTS_MODEL,
|
|
61
|
+
RECOMMENDED_TTS_OPTIONS,
|
|
57
62
|
RECOMMENDED_USE_GOOGLE_SEARCH_TOOL,
|
|
58
63
|
TIMEOUT_MILLIS,
|
|
59
64
|
)
|
|
@@ -66,12 +71,6 @@ STEP_API_DATA_SCHEMA = vol.Schema(
|
|
|
66
71
|
}
|
|
67
72
|
)
|
|
68
73
|
|
|
69
|
-
RECOMMENDED_OPTIONS = {
|
|
70
|
-
CONF_RECOMMENDED: True,
|
|
71
|
-
CONF_LLM_HASS_API: [llm.LLM_API_ASSIST],
|
|
72
|
-
CONF_PROMPT: llm.DEFAULT_INSTRUCTIONS_PROMPT,
|
|
73
|
-
}
|
|
74
|
-
|
|
75
74
|
|
|
76
75
|
async def validate_input(data: dict[str, Any]) -> None:
|
|
77
76
|
"""Validate the user input allows us to connect.
|
|
@@ -118,15 +117,21 @@ class GoogleGenerativeAIConfigFlow(ConfigFlow, domain=DOMAIN):
|
|
|
118
117
|
data=user_input,
|
|
119
118
|
)
|
|
120
119
|
return self.async_create_entry(
|
|
121
|
-
title=
|
|
120
|
+
title=DEFAULT_TITLE,
|
|
122
121
|
data=user_input,
|
|
123
122
|
subentries=[
|
|
124
123
|
{
|
|
125
124
|
"subentry_type": "conversation",
|
|
126
|
-
"data":
|
|
125
|
+
"data": RECOMMENDED_CONVERSATION_OPTIONS,
|
|
127
126
|
"title": DEFAULT_CONVERSATION_NAME,
|
|
128
127
|
"unique_id": None,
|
|
129
|
-
}
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"subentry_type": "tts",
|
|
131
|
+
"data": RECOMMENDED_TTS_OPTIONS,
|
|
132
|
+
"title": DEFAULT_TTS_NAME,
|
|
133
|
+
"unique_id": None,
|
|
134
|
+
},
|
|
130
135
|
],
|
|
131
136
|
)
|
|
132
137
|
return self.async_show_form(
|
|
@@ -172,10 +177,13 @@ class GoogleGenerativeAIConfigFlow(ConfigFlow, domain=DOMAIN):
|
|
|
172
177
|
cls, config_entry: ConfigEntry
|
|
173
178
|
) -> dict[str, type[ConfigSubentryFlow]]:
|
|
174
179
|
"""Return subentries supported by this integration."""
|
|
175
|
-
return {
|
|
180
|
+
return {
|
|
181
|
+
"conversation": LLMSubentryFlowHandler,
|
|
182
|
+
"tts": LLMSubentryFlowHandler,
|
|
183
|
+
}
|
|
176
184
|
|
|
177
185
|
|
|
178
|
-
class
|
|
186
|
+
class LLMSubentryFlowHandler(ConfigSubentryFlow):
|
|
179
187
|
"""Flow for managing conversation subentries."""
|
|
180
188
|
|
|
181
189
|
last_rendered_recommended = False
|
|
@@ -202,7 +210,11 @@ class ConversationSubentryFlowHandler(ConfigSubentryFlow):
|
|
|
202
210
|
|
|
203
211
|
if user_input is None:
|
|
204
212
|
if self._is_new:
|
|
205
|
-
options
|
|
213
|
+
options: dict[str, Any]
|
|
214
|
+
if self._subentry_type == "tts":
|
|
215
|
+
options = RECOMMENDED_TTS_OPTIONS.copy()
|
|
216
|
+
else:
|
|
217
|
+
options = RECOMMENDED_CONVERSATION_OPTIONS.copy()
|
|
206
218
|
else:
|
|
207
219
|
# If this is a reconfiguration, we need to copy the existing options
|
|
208
220
|
# so that we can show the current values in the form.
|
|
@@ -216,7 +228,7 @@ class ConversationSubentryFlowHandler(ConfigSubentryFlow):
|
|
|
216
228
|
if user_input[CONF_RECOMMENDED] == self.last_rendered_recommended:
|
|
217
229
|
if not user_input.get(CONF_LLM_HASS_API):
|
|
218
230
|
user_input.pop(CONF_LLM_HASS_API, None)
|
|
219
|
-
# Don't allow to save options that enable the Google
|
|
231
|
+
# Don't allow to save options that enable the Google Search tool with an Assist API
|
|
220
232
|
if not (
|
|
221
233
|
user_input.get(CONF_LLM_HASS_API)
|
|
222
234
|
and user_input.get(CONF_USE_GOOGLE_SEARCH_TOOL, False) is True
|
|
@@ -240,7 +252,7 @@ class ConversationSubentryFlowHandler(ConfigSubentryFlow):
|
|
|
240
252
|
options = user_input
|
|
241
253
|
|
|
242
254
|
schema = await google_generative_ai_config_option_schema(
|
|
243
|
-
self.hass, self._is_new, options, self._genai_client
|
|
255
|
+
self.hass, self._is_new, self._subentry_type, options, self._genai_client
|
|
244
256
|
)
|
|
245
257
|
return self.async_show_form(
|
|
246
258
|
step_id="set_options", data_schema=vol.Schema(schema), errors=errors
|
|
@@ -253,6 +265,7 @@ class ConversationSubentryFlowHandler(ConfigSubentryFlow):
|
|
|
253
265
|
async def google_generative_ai_config_option_schema(
|
|
254
266
|
hass: HomeAssistant,
|
|
255
267
|
is_new: bool,
|
|
268
|
+
subentry_type: str,
|
|
256
269
|
options: Mapping[str, Any],
|
|
257
270
|
genai_client: genai.Client,
|
|
258
271
|
) -> dict:
|
|
@@ -270,26 +283,39 @@ async def google_generative_ai_config_option_schema(
|
|
|
270
283
|
suggested_llm_apis = [suggested_llm_apis]
|
|
271
284
|
|
|
272
285
|
if is_new:
|
|
286
|
+
if CONF_NAME in options:
|
|
287
|
+
default_name = options[CONF_NAME]
|
|
288
|
+
elif subentry_type == "tts":
|
|
289
|
+
default_name = DEFAULT_TTS_NAME
|
|
290
|
+
else:
|
|
291
|
+
default_name = DEFAULT_CONVERSATION_NAME
|
|
273
292
|
schema: dict[vol.Required | vol.Optional, Any] = {
|
|
274
|
-
vol.Required(CONF_NAME, default=
|
|
293
|
+
vol.Required(CONF_NAME, default=default_name): str,
|
|
275
294
|
}
|
|
276
295
|
else:
|
|
277
296
|
schema = {}
|
|
278
297
|
|
|
298
|
+
if subentry_type == "conversation":
|
|
299
|
+
schema.update(
|
|
300
|
+
{
|
|
301
|
+
vol.Optional(
|
|
302
|
+
CONF_PROMPT,
|
|
303
|
+
description={
|
|
304
|
+
"suggested_value": options.get(
|
|
305
|
+
CONF_PROMPT, llm.DEFAULT_INSTRUCTIONS_PROMPT
|
|
306
|
+
)
|
|
307
|
+
},
|
|
308
|
+
): TemplateSelector(),
|
|
309
|
+
vol.Optional(
|
|
310
|
+
CONF_LLM_HASS_API,
|
|
311
|
+
description={"suggested_value": suggested_llm_apis},
|
|
312
|
+
): SelectSelector(
|
|
313
|
+
SelectSelectorConfig(options=hass_apis, multiple=True)
|
|
314
|
+
),
|
|
315
|
+
}
|
|
316
|
+
)
|
|
279
317
|
schema.update(
|
|
280
318
|
{
|
|
281
|
-
vol.Optional(
|
|
282
|
-
CONF_PROMPT,
|
|
283
|
-
description={
|
|
284
|
-
"suggested_value": options.get(
|
|
285
|
-
CONF_PROMPT, llm.DEFAULT_INSTRUCTIONS_PROMPT
|
|
286
|
-
)
|
|
287
|
-
},
|
|
288
|
-
): TemplateSelector(),
|
|
289
|
-
vol.Optional(
|
|
290
|
-
CONF_LLM_HASS_API,
|
|
291
|
-
description={"suggested_value": suggested_llm_apis},
|
|
292
|
-
): SelectSelector(SelectSelectorConfig(options=hass_apis, multiple=True)),
|
|
293
319
|
vol.Required(
|
|
294
320
|
CONF_RECOMMENDED, default=options.get(CONF_RECOMMENDED, False)
|
|
295
321
|
): bool,
|
|
@@ -310,7 +336,7 @@ async def google_generative_ai_config_option_schema(
|
|
|
310
336
|
if (
|
|
311
337
|
api_model.display_name
|
|
312
338
|
and api_model.name
|
|
313
|
-
and "tts"
|
|
339
|
+
and ("tts" in api_model.name) == (subentry_type == "tts")
|
|
314
340
|
and "vision" not in api_model.name
|
|
315
341
|
and api_model.supported_actions
|
|
316
342
|
and "generateContent" in api_model.supported_actions
|
|
@@ -341,12 +367,17 @@ async def google_generative_ai_config_option_schema(
|
|
|
341
367
|
)
|
|
342
368
|
)
|
|
343
369
|
|
|
370
|
+
if subentry_type == "tts":
|
|
371
|
+
default_model = RECOMMENDED_TTS_MODEL
|
|
372
|
+
else:
|
|
373
|
+
default_model = RECOMMENDED_CHAT_MODEL
|
|
374
|
+
|
|
344
375
|
schema.update(
|
|
345
376
|
{
|
|
346
377
|
vol.Optional(
|
|
347
378
|
CONF_CHAT_MODEL,
|
|
348
379
|
description={"suggested_value": options.get(CONF_CHAT_MODEL)},
|
|
349
|
-
default=
|
|
380
|
+
default=default_model,
|
|
350
381
|
): SelectSelector(
|
|
351
382
|
SelectSelectorConfig(mode=SelectSelectorMode.DROPDOWN, options=models)
|
|
352
383
|
),
|
|
@@ -396,13 +427,18 @@ async def google_generative_ai_config_option_schema(
|
|
|
396
427
|
},
|
|
397
428
|
default=RECOMMENDED_HARM_BLOCK_THRESHOLD,
|
|
398
429
|
): harm_block_thresholds_selector,
|
|
399
|
-
vol.Optional(
|
|
400
|
-
CONF_USE_GOOGLE_SEARCH_TOOL,
|
|
401
|
-
description={
|
|
402
|
-
"suggested_value": options.get(CONF_USE_GOOGLE_SEARCH_TOOL),
|
|
403
|
-
},
|
|
404
|
-
default=RECOMMENDED_USE_GOOGLE_SEARCH_TOOL,
|
|
405
|
-
): bool,
|
|
406
430
|
}
|
|
407
431
|
)
|
|
432
|
+
if subentry_type == "conversation":
|
|
433
|
+
schema.update(
|
|
434
|
+
{
|
|
435
|
+
vol.Optional(
|
|
436
|
+
CONF_USE_GOOGLE_SEARCH_TOOL,
|
|
437
|
+
description={
|
|
438
|
+
"suggested_value": options.get(CONF_USE_GOOGLE_SEARCH_TOOL),
|
|
439
|
+
},
|
|
440
|
+
default=RECOMMENDED_USE_GOOGLE_SEARCH_TOOL,
|
|
441
|
+
): bool,
|
|
442
|
+
}
|
|
443
|
+
)
|
|
408
444
|
return schema
|
|
@@ -2,17 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
|
|
5
|
+
from homeassistant.const import CONF_LLM_HASS_API
|
|
6
|
+
from homeassistant.helpers import llm
|
|
7
|
+
|
|
5
8
|
DOMAIN = "google_generative_ai_conversation"
|
|
9
|
+
DEFAULT_TITLE = "Google Generative AI"
|
|
6
10
|
LOGGER = logging.getLogger(__package__)
|
|
7
11
|
CONF_PROMPT = "prompt"
|
|
8
12
|
|
|
9
13
|
DEFAULT_CONVERSATION_NAME = "Google AI Conversation"
|
|
14
|
+
DEFAULT_TTS_NAME = "Google AI TTS"
|
|
10
15
|
|
|
11
|
-
ATTR_MODEL = "model"
|
|
12
16
|
CONF_RECOMMENDED = "recommended"
|
|
13
17
|
CONF_CHAT_MODEL = "chat_model"
|
|
14
18
|
RECOMMENDED_CHAT_MODEL = "models/gemini-2.5-flash"
|
|
15
|
-
RECOMMENDED_TTS_MODEL = "gemini-2.5-flash-preview-tts"
|
|
19
|
+
RECOMMENDED_TTS_MODEL = "models/gemini-2.5-flash-preview-tts"
|
|
16
20
|
CONF_TEMPERATURE = "temperature"
|
|
17
21
|
RECOMMENDED_TEMPERATURE = 1.0
|
|
18
22
|
CONF_TOP_P = "top_p"
|
|
@@ -31,3 +35,12 @@ RECOMMENDED_USE_GOOGLE_SEARCH_TOOL = False
|
|
|
31
35
|
|
|
32
36
|
TIMEOUT_MILLIS = 10000
|
|
33
37
|
FILE_POLLING_INTERVAL_SECONDS = 0.05
|
|
38
|
+
RECOMMENDED_CONVERSATION_OPTIONS = {
|
|
39
|
+
CONF_PROMPT: llm.DEFAULT_INSTRUCTIONS_PROMPT,
|
|
40
|
+
CONF_LLM_HASS_API: [llm.LLM_API_ASSIST],
|
|
41
|
+
CONF_RECOMMENDED: True,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
RECOMMENDED_TTS_OPTIONS = {
|
|
45
|
+
CONF_RECOMMENDED: True,
|
|
46
|
+
}
|
|
@@ -301,7 +301,12 @@ async def _transform_stream(
|
|
|
301
301
|
class GoogleGenerativeAILLMBaseEntity(Entity):
|
|
302
302
|
"""Google Generative AI base entity."""
|
|
303
303
|
|
|
304
|
-
def __init__(
|
|
304
|
+
def __init__(
|
|
305
|
+
self,
|
|
306
|
+
entry: ConfigEntry,
|
|
307
|
+
subentry: ConfigSubentry,
|
|
308
|
+
default_model: str = RECOMMENDED_CHAT_MODEL,
|
|
309
|
+
) -> None:
|
|
305
310
|
"""Initialize the agent."""
|
|
306
311
|
self.entry = entry
|
|
307
312
|
self.subentry = subentry
|
|
@@ -312,7 +317,7 @@ class GoogleGenerativeAILLMBaseEntity(Entity):
|
|
|
312
317
|
identifiers={(DOMAIN, subentry.subentry_id)},
|
|
313
318
|
name=subentry.title,
|
|
314
319
|
manufacturer="Google",
|
|
315
|
-
model=
|
|
320
|
+
model=subentry.data.get(CONF_CHAT_MODEL, default_model).split("/")[-1],
|
|
316
321
|
entry_type=dr.DeviceEntryType.SERVICE,
|
|
317
322
|
)
|
|
318
323
|
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""Helper classes for Google Generative AI integration."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from contextlib import suppress
|
|
6
|
+
import io
|
|
7
|
+
import wave
|
|
8
|
+
|
|
9
|
+
from homeassistant.exceptions import HomeAssistantError
|
|
10
|
+
|
|
11
|
+
from .const import LOGGER
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def convert_to_wav(audio_data: bytes, mime_type: str) -> bytes:
|
|
15
|
+
"""Generate a WAV file header for the given audio data and parameters.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
audio_data: The raw audio data as a bytes object.
|
|
19
|
+
mime_type: Mime type of the audio data.
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
A bytes object representing the WAV file header.
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
parameters = _parse_audio_mime_type(mime_type)
|
|
26
|
+
|
|
27
|
+
wav_buffer = io.BytesIO()
|
|
28
|
+
with wave.open(wav_buffer, "wb") as wf:
|
|
29
|
+
wf.setnchannels(1)
|
|
30
|
+
wf.setsampwidth(parameters["bits_per_sample"] // 8)
|
|
31
|
+
wf.setframerate(parameters["rate"])
|
|
32
|
+
wf.writeframes(audio_data)
|
|
33
|
+
|
|
34
|
+
return wav_buffer.getvalue()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# Below code is from https://aistudio.google.com/app/generate-speech
|
|
38
|
+
# when you select "Get SDK code to generate speech".
|
|
39
|
+
def _parse_audio_mime_type(mime_type: str) -> dict[str, int]:
|
|
40
|
+
"""Parse bits per sample and rate from an audio MIME type string.
|
|
41
|
+
|
|
42
|
+
Assumes bits per sample is encoded like "L16" and rate as "rate=xxxxx".
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
mime_type: The audio MIME type string (e.g., "audio/L16;rate=24000").
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
A dictionary with "bits_per_sample" and "rate" keys. Values will be
|
|
49
|
+
integers if found, otherwise None.
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
if not mime_type.startswith("audio/L"):
|
|
53
|
+
LOGGER.warning("Received unexpected MIME type %s", mime_type)
|
|
54
|
+
raise HomeAssistantError(f"Unsupported audio MIME type: {mime_type}")
|
|
55
|
+
|
|
56
|
+
bits_per_sample = 16
|
|
57
|
+
rate = 24000
|
|
58
|
+
|
|
59
|
+
# Extract rate from parameters
|
|
60
|
+
parts = mime_type.split(";")
|
|
61
|
+
for param in parts: # Skip the main type part
|
|
62
|
+
param = param.strip()
|
|
63
|
+
if param.lower().startswith("rate="):
|
|
64
|
+
# Handle cases like "rate=" with no value or non-integer value and keep rate as default
|
|
65
|
+
with suppress(ValueError, IndexError):
|
|
66
|
+
rate_str = param.split("=", 1)[1]
|
|
67
|
+
rate = int(rate_str)
|
|
68
|
+
elif param.startswith("audio/L"):
|
|
69
|
+
# Keep bits_per_sample as default if conversion fails
|
|
70
|
+
with suppress(ValueError, IndexError):
|
|
71
|
+
bits_per_sample = int(param.split("L", 1)[1])
|
|
72
|
+
|
|
73
|
+
return {"bits_per_sample": bits_per_sample, "rate": rate}
|
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
"reconfigure": "Reconfigure conversation agent"
|
|
30
30
|
},
|
|
31
31
|
"entry_type": "Conversation agent",
|
|
32
|
-
|
|
33
32
|
"step": {
|
|
34
33
|
"set_options": {
|
|
35
34
|
"data": {
|
|
@@ -61,6 +60,34 @@
|
|
|
61
60
|
"error": {
|
|
62
61
|
"invalid_google_search_option": "Google Search can only be enabled if nothing is selected in the \"Control Home Assistant\" setting."
|
|
63
62
|
}
|
|
63
|
+
},
|
|
64
|
+
"tts": {
|
|
65
|
+
"initiate_flow": {
|
|
66
|
+
"user": "Add Text-to-Speech service",
|
|
67
|
+
"reconfigure": "Reconfigure Text-to-Speech service"
|
|
68
|
+
},
|
|
69
|
+
"entry_type": "Text-to-Speech",
|
|
70
|
+
"step": {
|
|
71
|
+
"set_options": {
|
|
72
|
+
"data": {
|
|
73
|
+
"name": "[%key:common::config_flow::data::name%]",
|
|
74
|
+
"recommended": "[%key:component::google_generative_ai_conversation::config_subentries::conversation::step::set_options::data::recommended%]",
|
|
75
|
+
"chat_model": "[%key:common::generic::model%]",
|
|
76
|
+
"temperature": "[%key:component::google_generative_ai_conversation::config_subentries::conversation::step::set_options::data::temperature%]",
|
|
77
|
+
"top_p": "[%key:component::google_generative_ai_conversation::config_subentries::conversation::step::set_options::data::top_p%]",
|
|
78
|
+
"top_k": "[%key:component::google_generative_ai_conversation::config_subentries::conversation::step::set_options::data::top_k%]",
|
|
79
|
+
"max_tokens": "[%key:component::google_generative_ai_conversation::config_subentries::conversation::step::set_options::data::max_tokens%]",
|
|
80
|
+
"harassment_block_threshold": "[%key:component::google_generative_ai_conversation::config_subentries::conversation::step::set_options::data::harassment_block_threshold%]",
|
|
81
|
+
"hate_block_threshold": "[%key:component::google_generative_ai_conversation::config_subentries::conversation::step::set_options::data::hate_block_threshold%]",
|
|
82
|
+
"sexual_block_threshold": "[%key:component::google_generative_ai_conversation::config_subentries::conversation::step::set_options::data::sexual_block_threshold%]",
|
|
83
|
+
"dangerous_block_threshold": "[%key:component::google_generative_ai_conversation::config_subentries::conversation::step::set_options::data::dangerous_block_threshold%]"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"abort": {
|
|
88
|
+
"entry_not_loaded": "[%key:component::google_generative_ai_conversation::config_subentries::conversation::abort::entry_not_loaded%]",
|
|
89
|
+
"reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]"
|
|
90
|
+
}
|
|
64
91
|
}
|
|
65
92
|
},
|
|
66
93
|
"services": {
|
|
@@ -34,6 +34,25 @@
|
|
|
34
34
|
"llm_hass_api": "\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430 Home Assistant",
|
|
35
35
|
"name": "\u0418\u043c\u0435",
|
|
36
36
|
"prompt": "\u0418\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438",
|
|
37
|
+
"recommended": "\u041f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0438\u0442\u0435\u043b\u043d\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430 \u043c\u043e\u0434\u0435\u043b\u0430",
|
|
38
|
+
"sexual_block_threshold": "\u0421\u044a\u0434\u044a\u0440\u0436\u0430 \u043f\u0440\u0435\u043f\u0440\u0430\u0442\u043a\u0438 \u043a\u044a\u043c \u0441\u0435\u043a\u0441\u0443\u0430\u043b\u043d\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e \u043d\u0435\u043f\u0440\u0438\u043b\u0438\u0447\u043d\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435",
|
|
39
|
+
"temperature": "\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"tts": {
|
|
45
|
+
"abort": {
|
|
46
|
+
"reconfigure_successful": "\u041f\u0440\u0435\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u0435\u0442\u043e \u0431\u0435\u0448\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e"
|
|
47
|
+
},
|
|
48
|
+
"entry_type": "\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0432\u0430\u043d\u0435 \u043d\u0430 \u0442\u0435\u043a\u0441\u0442 \u0432 \u0440\u0435\u0447",
|
|
49
|
+
"step": {
|
|
50
|
+
"set_options": {
|
|
51
|
+
"data": {
|
|
52
|
+
"chat_model": "\u041c\u043e\u0434\u0435\u043b",
|
|
53
|
+
"name": "\u0418\u043c\u0435",
|
|
54
|
+
"recommended": "\u041f\u0440\u0435\u043f\u043e\u0440\u044a\u0447\u0438\u0442\u0435\u043b\u043d\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430 \u043c\u043e\u0434\u0435\u043b\u0430",
|
|
55
|
+
"sexual_block_threshold": "\u0421\u044a\u0434\u044a\u0440\u0436\u0430 \u043f\u0440\u0435\u043f\u0440\u0430\u0442\u043a\u0438 \u043a\u044a\u043c \u0441\u0435\u043a\u0441\u0443\u0430\u043b\u043d\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e \u043d\u0435\u043f\u0440\u0438\u043b\u0438\u0447\u043d\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435",
|
|
37
56
|
"temperature": "\u0422\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u0430"
|
|
38
57
|
}
|
|
39
58
|
}
|