From b8369a58315632d293caeae068392873cfe97ada Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Mon, 10 Jul 2023 19:42:13 +0200 Subject: [PATCH 001/154] Add entity translations to trafikverket weatherstation (#96251) --- .../trafikverket_weatherstation/sensor.py | 20 ++++------ .../trafikverket_weatherstation/strings.json | 38 ++++++++++++++----- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/homeassistant/components/trafikverket_weatherstation/sensor.py b/homeassistant/components/trafikverket_weatherstation/sensor.py index 8523ded1fffc3f..f34eae3cf1fcb8 100644 --- a/homeassistant/components/trafikverket_weatherstation/sensor.py +++ b/homeassistant/components/trafikverket_weatherstation/sensor.py @@ -87,32 +87,33 @@ class TrafikverketSensorEntityDescription( SENSOR_TYPES: tuple[TrafikverketSensorEntityDescription, ...] = ( TrafikverketSensorEntityDescription( key="air_temp", + translation_key="air_temperature", api_key="air_temp", - name="Air temperature", native_unit_of_measurement=UnitOfTemperature.CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, ), TrafikverketSensorEntityDescription( key="road_temp", + translation_key="road_temperature", api_key="road_temp", - name="Road temperature", native_unit_of_measurement=UnitOfTemperature.CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, ), TrafikverketSensorEntityDescription( key="precipitation", + translation_key="precipitation", api_key="precipitationtype_translated", name="Precipitation type", icon="mdi:weather-snowy-rainy", entity_registry_enabled_default=False, - translation_key="precipitation", options=PRECIPITATION_TYPE, device_class=SensorDeviceClass.ENUM, ), TrafikverketSensorEntityDescription( key="wind_direction", + translation_key="wind_direction", api_key="winddirection", name="Wind direction", native_unit_of_measurement=DEGREE, @@ -121,25 +122,24 @@ class TrafikverketSensorEntityDescription( ), TrafikverketSensorEntityDescription( key="wind_direction_text", + translation_key="wind_direction_text", api_key="winddirectiontext_translated", name="Wind direction text", icon="mdi:flag-triangle", - translation_key="wind_direction_text", options=WIND_DIRECTIONS, device_class=SensorDeviceClass.ENUM, ), TrafikverketSensorEntityDescription( key="wind_speed", api_key="windforce", - name="Wind speed", native_unit_of_measurement=UnitOfSpeed.METERS_PER_SECOND, device_class=SensorDeviceClass.WIND_SPEED, state_class=SensorStateClass.MEASUREMENT, ), TrafikverketSensorEntityDescription( key="wind_speed_max", + translation_key="wind_speed_max", api_key="windforcemax", - name="Wind speed max", native_unit_of_measurement=UnitOfSpeed.METERS_PER_SECOND, device_class=SensorDeviceClass.WIND_SPEED, icon="mdi:weather-windy-variant", @@ -149,9 +149,7 @@ class TrafikverketSensorEntityDescription( TrafikverketSensorEntityDescription( key="humidity", api_key="humidity", - name="Humidity", native_unit_of_measurement=PERCENTAGE, - icon="mdi:water-percent", device_class=SensorDeviceClass.HUMIDITY, entity_registry_enabled_default=False, state_class=SensorStateClass.MEASUREMENT, @@ -159,25 +157,23 @@ class TrafikverketSensorEntityDescription( TrafikverketSensorEntityDescription( key="precipitation_amount", api_key="precipitation_amount", - name="Precipitation amount", native_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR, device_class=SensorDeviceClass.PRECIPITATION_INTENSITY, state_class=SensorStateClass.MEASUREMENT, ), TrafikverketSensorEntityDescription( key="precipitation_amountname", + translation_key="precipitation_amountname", api_key="precipitation_amountname_translated", - name="Precipitation name", icon="mdi:weather-pouring", entity_registry_enabled_default=False, - translation_key="precipitation_amountname", options=PRECIPITATION_AMOUNTNAME, device_class=SensorDeviceClass.ENUM, ), TrafikverketSensorEntityDescription( key="measure_time", + translation_key="measure_time", api_key="measure_time", - name="Measure Time", icon="mdi:clock", entity_registry_enabled_default=False, device_class=SensorDeviceClass.TIMESTAMP, diff --git a/homeassistant/components/trafikverket_weatherstation/strings.json b/homeassistant/components/trafikverket_weatherstation/strings.json index 3680fae6d8c626..9ff1b077f33b92 100644 --- a/homeassistant/components/trafikverket_weatherstation/strings.json +++ b/homeassistant/components/trafikverket_weatherstation/strings.json @@ -20,7 +20,29 @@ }, "entity": { "sensor": { + "air_temperature": { + "name": "Air temperature" + }, + "road_temperature": { + "name": "Road temperature" + }, + "precipitation": { + "name": "Precipitation type", + "state": { + "drizzle": "Drizzle", + "hail": "Hail", + "none": "None", + "rain": "Rain", + "snow": "Snow", + "rain_snow_mixed": "Rain and snow mixed", + "freezing_rain": "Freezing rain" + } + }, + "wind_direction": { + "name": "Wind direction" + }, "wind_direction_text": { + "name": "Wind direction text", "state": { "east": "East", "north_east": "North east", @@ -36,7 +58,11 @@ "west": "West" } }, + "wind_speed_max": { + "name": "Wind speed max" + }, "precipitation_amountname": { + "name": "Precipitation name", "state": { "error": "Error", "mild_rain": "Mild rain", @@ -53,16 +79,8 @@ "unknown": "Unknown" } }, - "precipitation": { - "state": { - "drizzle": "Drizzle", - "hail": "Hail", - "none": "None", - "rain": "Rain", - "snow": "Snow", - "rain_snow_mixed": "Rain and snow mixed", - "freezing_rain": "Freezing rain" - } + "measure_time": { + "name": "Measure time" } } } From 7f666849c2bde7ac7a040a9708290b2956785531 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Mon, 10 Jul 2023 20:20:36 +0200 Subject: [PATCH 002/154] Add filters to siren/services.yaml (#95864) --- homeassistant/components/siren/services.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/homeassistant/components/siren/services.yaml b/homeassistant/components/siren/services.yaml index 209dece71ab8d4..154ffff78a3a12 100644 --- a/homeassistant/components/siren/services.yaml +++ b/homeassistant/components/siren/services.yaml @@ -6,16 +6,24 @@ turn_on: target: entity: domain: siren + supported_features: + - siren.SirenEntityFeature.TURN_ON fields: tone: description: The tone to emit when turning the siren on. When `available_tones` property is a map, either the key or the value can be used. Must be supported by the integration. example: fire + filter: + supported_features: + - siren.SirenEntityFeature.TONES required: false selector: text: volume_level: description: The volume level of the noise to emit when turning the siren on. Must be supported by the integration. example: 0.5 + filter: + supported_features: + - siren.SirenEntityFeature.VOLUME_SET required: false selector: number: @@ -25,6 +33,9 @@ turn_on: duration: description: The duration in seconds of the noise to emit when turning the siren on. Must be supported by the integration. example: 15 + filter: + supported_features: + - siren.SirenEntityFeature.DURATION required: false selector: text: @@ -35,6 +46,8 @@ turn_off: target: entity: domain: siren + supported_features: + - siren.SirenEntityFeature.TURN_OFF toggle: name: Toggle @@ -42,3 +55,6 @@ toggle: target: entity: domain: siren + supported_features: + - - siren.SirenEntityFeature.TURN_OFF + - siren.SirenEntityFeature.TURN_ON From 22357701f0ccc630b1e74fcd62bcb5cb49263409 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Mon, 10 Jul 2023 20:21:28 +0200 Subject: [PATCH 003/154] Add filters to media_player/services.yaml (#95862) --- .../components/media_player/services.yaml | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/homeassistant/components/media_player/services.yaml b/homeassistant/components/media_player/services.yaml index 21807262742248..97605886036a27 100644 --- a/homeassistant/components/media_player/services.yaml +++ b/homeassistant/components/media_player/services.yaml @@ -6,6 +6,8 @@ turn_on: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.TURN_ON turn_off: name: Turn off @@ -13,6 +15,8 @@ turn_off: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.TURN_OFF toggle: name: Toggle @@ -20,6 +24,9 @@ toggle: target: entity: domain: media_player + supported_features: + - - media_player.MediaPlayerEntityFeature.TURN_OFF + - media_player.MediaPlayerEntityFeature.TURN_ON volume_up: name: Turn up volume @@ -27,6 +34,9 @@ volume_up: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.VOLUME_SET + - media_player.MediaPlayerEntityFeature.VOLUME_STEP volume_down: name: Turn down volume @@ -34,6 +44,9 @@ volume_down: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.VOLUME_SET + - media_player.MediaPlayerEntityFeature.VOLUME_STEP volume_mute: name: Mute volume @@ -41,6 +54,8 @@ volume_mute: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.VOLUME_MUTE fields: is_volume_muted: name: Muted @@ -55,6 +70,8 @@ volume_set: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.VOLUME_SET fields: volume_level: name: Level @@ -72,6 +89,9 @@ media_play_pause: target: entity: domain: media_player + supported_features: + - - media_player.MediaPlayerEntityFeature.PAUSE + - media_player.MediaPlayerEntityFeature.PLAY media_play: name: Play @@ -79,6 +99,8 @@ media_play: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.PLAY media_pause: name: Pause @@ -86,6 +108,8 @@ media_pause: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.PAUSE media_stop: name: Stop @@ -93,6 +117,8 @@ media_stop: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.STOP media_next_track: name: Next @@ -100,6 +126,8 @@ media_next_track: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.NEXT_TRACK media_previous_track: name: Previous @@ -107,6 +135,8 @@ media_previous_track: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.PREVIOUS_TRACK media_seek: name: Seek @@ -114,6 +144,8 @@ media_seek: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.SEEK fields: seek_position: name: Position @@ -132,6 +164,8 @@ play_media: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.PLAY_MEDIA fields: media_content_id: name: Content ID @@ -186,6 +220,8 @@ select_source: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.SELECT_SOURCE fields: source: name: Source @@ -201,6 +237,8 @@ select_sound_mode: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.SELECT_SOUND_MODE fields: sound_mode: name: Sound mode @@ -215,6 +253,8 @@ clear_playlist: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.CLEAR_PLAYLIST shuffle_set: name: Shuffle @@ -222,6 +262,8 @@ shuffle_set: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.SHUFFLE_SET fields: shuffle: name: Shuffle @@ -236,6 +278,8 @@ repeat_set: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.REPEAT_SET fields: repeat: name: Repeat mode @@ -259,6 +303,8 @@ join: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.GROUPING fields: group_members: name: Group members @@ -280,3 +326,5 @@ unjoin: target: entity: domain: media_player + supported_features: + - media_player.MediaPlayerEntityFeature.GROUPING From d973e43b9013f4c4959c00e264a467fec2514f2e Mon Sep 17 00:00:00 2001 From: David Knowles Date: Tue, 11 Jul 2023 00:26:02 -0400 Subject: [PATCH 004/154] Move Hydrawise to a supported library (#96023) --- homeassistant/components/hydrawise/__init__.py | 4 ++-- homeassistant/components/hydrawise/binary_sensor.py | 4 ++-- homeassistant/components/hydrawise/coordinator.py | 4 ++-- homeassistant/components/hydrawise/manifest.json | 4 ++-- homeassistant/components/hydrawise/sensor.py | 4 ++-- homeassistant/components/hydrawise/switch.py | 4 ++-- requirements_all.txt | 6 +++--- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/hydrawise/__init__.py b/homeassistant/components/hydrawise/__init__.py index e09cabb74fc7fc..6d9f2747847e65 100644 --- a/homeassistant/components/hydrawise/__init__.py +++ b/homeassistant/components/hydrawise/__init__.py @@ -1,7 +1,7 @@ """Support for Hydrawise cloud.""" -from hydrawiser.core import Hydrawiser +from pydrawise.legacy import LegacyHydrawise from requests.exceptions import ConnectTimeout, HTTPError import voluptuous as vol @@ -34,7 +34,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: scan_interval = conf.get(CONF_SCAN_INTERVAL) try: - hydrawise = await hass.async_add_executor_job(Hydrawiser, access_token) + hydrawise = await hass.async_add_executor_job(LegacyHydrawise, access_token) except (ConnectTimeout, HTTPError) as ex: LOGGER.error("Unable to connect to Hydrawise cloud service: %s", str(ex)) _show_failure_notification(hass, str(ex)) diff --git a/homeassistant/components/hydrawise/binary_sensor.py b/homeassistant/components/hydrawise/binary_sensor.py index 2986bbb170eafd..bc9b8722c58ccd 100644 --- a/homeassistant/components/hydrawise/binary_sensor.py +++ b/homeassistant/components/hydrawise/binary_sensor.py @@ -1,7 +1,7 @@ """Support for Hydrawise sprinkler binary sensors.""" from __future__ import annotations -from hydrawiser.core import Hydrawiser +from pydrawise.legacy import LegacyHydrawise import voluptuous as vol from homeassistant.components.binary_sensor import ( @@ -55,7 +55,7 @@ def setup_platform( ) -> None: """Set up a sensor for a Hydrawise device.""" coordinator: HydrawiseDataUpdateCoordinator = hass.data[DOMAIN] - hydrawise: Hydrawiser = coordinator.api + hydrawise: LegacyHydrawise = coordinator.api monitored_conditions = config[CONF_MONITORED_CONDITIONS] entities = [] diff --git a/homeassistant/components/hydrawise/coordinator.py b/homeassistant/components/hydrawise/coordinator.py index ea2e2dd2c4c017..007b15d2403dda 100644 --- a/homeassistant/components/hydrawise/coordinator.py +++ b/homeassistant/components/hydrawise/coordinator.py @@ -4,7 +4,7 @@ from datetime import timedelta -from hydrawiser.core import Hydrawiser +from pydrawise.legacy import LegacyHydrawise from homeassistant.core import HomeAssistant from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed @@ -16,7 +16,7 @@ class HydrawiseDataUpdateCoordinator(DataUpdateCoordinator[None]): """The Hydrawise Data Update Coordinator.""" def __init__( - self, hass: HomeAssistant, api: Hydrawiser, scan_interval: timedelta + self, hass: HomeAssistant, api: LegacyHydrawise, scan_interval: timedelta ) -> None: """Initialize HydrawiseDataUpdateCoordinator.""" super().__init__(hass, LOGGER, name=DOMAIN, update_interval=scan_interval) diff --git a/homeassistant/components/hydrawise/manifest.json b/homeassistant/components/hydrawise/manifest.json index fc88c08b27ae02..48c9cdcf042d6c 100644 --- a/homeassistant/components/hydrawise/manifest.json +++ b/homeassistant/components/hydrawise/manifest.json @@ -4,6 +4,6 @@ "codeowners": ["@dknowles2", "@ptcryan"], "documentation": "https://www.home-assistant.io/integrations/hydrawise", "iot_class": "cloud_polling", - "loggers": ["hydrawiser"], - "requirements": ["Hydrawiser==0.2"] + "loggers": ["pydrawise"], + "requirements": ["pydrawise==2023.7.0"] } diff --git a/homeassistant/components/hydrawise/sensor.py b/homeassistant/components/hydrawise/sensor.py index d1334143375d53..9214b9daeaca09 100644 --- a/homeassistant/components/hydrawise/sensor.py +++ b/homeassistant/components/hydrawise/sensor.py @@ -1,7 +1,7 @@ """Support for Hydrawise sprinkler sensors.""" from __future__ import annotations -from hydrawiser.core import Hydrawiser +from pydrawise.legacy import LegacyHydrawise import voluptuous as vol from homeassistant.components.sensor import ( @@ -57,7 +57,7 @@ def setup_platform( ) -> None: """Set up a sensor for a Hydrawise device.""" coordinator: HydrawiseDataUpdateCoordinator = hass.data[DOMAIN] - hydrawise: Hydrawiser = coordinator.api + hydrawise: LegacyHydrawise = coordinator.api monitored_conditions = config[CONF_MONITORED_CONDITIONS] entities = [ diff --git a/homeassistant/components/hydrawise/switch.py b/homeassistant/components/hydrawise/switch.py index 00089bb8774f75..dbd2c08b28ea91 100644 --- a/homeassistant/components/hydrawise/switch.py +++ b/homeassistant/components/hydrawise/switch.py @@ -3,7 +3,7 @@ from typing import Any -from hydrawiser.core import Hydrawiser +from pydrawise.legacy import LegacyHydrawise import voluptuous as vol from homeassistant.components.switch import ( @@ -63,7 +63,7 @@ def setup_platform( ) -> None: """Set up a sensor for a Hydrawise device.""" coordinator: HydrawiseDataUpdateCoordinator = hass.data[DOMAIN] - hydrawise: Hydrawiser = coordinator.api + hydrawise: LegacyHydrawise = coordinator.api monitored_conditions: list[str] = config[CONF_MONITORED_CONDITIONS] default_watering_timer: int = config[CONF_WATERING_TIME] diff --git a/requirements_all.txt b/requirements_all.txt index 567b8a96d5c340..44d3f4834f8183 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -31,9 +31,6 @@ HAP-python==4.7.0 # homeassistant.components.tasmota HATasmota==0.6.5 -# homeassistant.components.hydrawise -Hydrawiser==0.2 - # homeassistant.components.mastodon Mastodon.py==1.5.1 @@ -1638,6 +1635,9 @@ pydiscovergy==1.2.1 # homeassistant.components.doods pydoods==1.0.2 +# homeassistant.components.hydrawise +pydrawise==2023.7.0 + # homeassistant.components.android_ip_webcam pydroid-ipcam==2.0.0 From aec0694823f514e34a1275ebb67f40ced7985848 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Tue, 11 Jul 2023 08:09:57 +0200 Subject: [PATCH 005/154] Move tractive attribute to entity class (#96247) Clean up tractive entities --- homeassistant/components/tractive/binary_sensor.py | 2 -- homeassistant/components/tractive/device_tracker.py | 1 - homeassistant/components/tractive/entity.py | 2 ++ homeassistant/components/tractive/sensor.py | 2 -- homeassistant/components/tractive/switch.py | 1 - 5 files changed, 2 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/tractive/binary_sensor.py b/homeassistant/components/tractive/binary_sensor.py index 4b376941344047..cb4abc9b385a0d 100644 --- a/homeassistant/components/tractive/binary_sensor.py +++ b/homeassistant/components/tractive/binary_sensor.py @@ -30,8 +30,6 @@ class TractiveBinarySensor(TractiveEntity, BinarySensorEntity): """Tractive sensor.""" - _attr_has_entity_name = True - def __init__( self, user_id: str, item: Trackables, description: BinarySensorEntityDescription ) -> None: diff --git a/homeassistant/components/tractive/device_tracker.py b/homeassistant/components/tractive/device_tracker.py index 038461494d6f01..e9739819734fe2 100644 --- a/homeassistant/components/tractive/device_tracker.py +++ b/homeassistant/components/tractive/device_tracker.py @@ -36,7 +36,6 @@ async def async_setup_entry( class TractiveDeviceTracker(TractiveEntity, TrackerEntity): """Tractive device tracker.""" - _attr_has_entity_name = True _attr_icon = "mdi:paw" _attr_translation_key = "tracker" diff --git a/homeassistant/components/tractive/entity.py b/homeassistant/components/tractive/entity.py index def321d928f192..712f8eda75a7db 100644 --- a/homeassistant/components/tractive/entity.py +++ b/homeassistant/components/tractive/entity.py @@ -11,6 +11,8 @@ class TractiveEntity(Entity): """Tractive entity class.""" + _attr_has_entity_name = True + def __init__( self, user_id: str, trackable: dict[str, Any], tracker_details: dict[str, Any] ) -> None: diff --git a/homeassistant/components/tractive/sensor.py b/homeassistant/components/tractive/sensor.py index 9c0f8f307edc07..24439b489c8a73 100644 --- a/homeassistant/components/tractive/sensor.py +++ b/homeassistant/components/tractive/sensor.py @@ -52,8 +52,6 @@ class TractiveSensorEntityDescription( class TractiveSensor(TractiveEntity, SensorEntity): """Tractive sensor.""" - _attr_has_entity_name = True - def __init__( self, user_id: str, diff --git a/homeassistant/components/tractive/switch.py b/homeassistant/components/tractive/switch.py index 7ae480d4f98a17..6d8274df2538e9 100644 --- a/homeassistant/components/tractive/switch.py +++ b/homeassistant/components/tractive/switch.py @@ -88,7 +88,6 @@ async def async_setup_entry( class TractiveSwitch(TractiveEntity, SwitchEntity): """Tractive switch.""" - _attr_has_entity_name = True entity_description: TractiveSwitchEntityDescription def __init__( From 6aa2ede6c7337e627cf1694a42f9a0f0b4746a00 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 11 Jul 2023 08:45:45 +0200 Subject: [PATCH 006/154] Correct issues raised when calling deprecated vacuum services (#96295) --- homeassistant/components/roborock/strings.json | 9 ++++++++- homeassistant/components/tuya/strings.json | 18 ++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/roborock/strings.json b/homeassistant/components/roborock/strings.json index 70ed98a6d5fa2c..63ebd31b34c305 100644 --- a/homeassistant/components/roborock/strings.json +++ b/homeassistant/components/roborock/strings.json @@ -175,7 +175,14 @@ "issues": { "service_deprecation_start_pause": { "title": "Roborock vacuum support for vacuum.start_pause is being removed", - "description": "Roborock vacuum support for the vacuum.start_pause service is deprecated and will be removed in Home Assistant 2024.2; Please adjust any automation or script that uses the service to instead call vacuum.pause or vacuum.start and select submit below to mark this issue as resolved." + "fix_flow": { + "step": { + "confirm": { + "title": "[%key:component::roborock::issues::service_deprecation_start_pause::title%]", + "description": "Roborock vacuum support for the vacuum.start_pause service is deprecated and will be removed in Home Assistant 2024.2; Please adjust any automation or script that uses the service to instead call vacuum.pause or vacuum.start and select submit below to mark this issue as resolved." + } + } + } } } } diff --git a/homeassistant/components/tuya/strings.json b/homeassistant/components/tuya/strings.json index 0cab59de2912c8..f4443e89f76029 100644 --- a/homeassistant/components/tuya/strings.json +++ b/homeassistant/components/tuya/strings.json @@ -216,11 +216,25 @@ "issues": { "service_deprecation_turn_off": { "title": "Tuya vacuum support for vacuum.turn_off is being removed", - "description": "Tuya vacuum support for the vacuum.turn_off service is deprecated and will be removed in Home Assistant 2024.2; Please adjust any automation or script that uses the service to instead call vacuum.stop and select submit below to mark this issue as resolved." + "fix_flow": { + "step": { + "confirm": { + "title": "[%key:component::tuya::issues::service_deprecation_turn_off::title%]", + "description": "Tuya vacuum support for the vacuum.turn_off service is deprecated and will be removed in Home Assistant 2024.2; Please adjust any automation or script that uses the service to instead call vacuum.stop and select submit below to mark this issue as resolved." + } + } + } }, "service_deprecation_turn_on": { "title": "Tuya vacuum support for vacuum.turn_on is being removed", - "description": "Tuya vacuum support for the vacuum.turn_on service is deprecated and will be removed in Home Assistant 2024.2; Please adjust any automation or script that uses the service to instead call vacuum.start and select submit below to mark this issue as resolved." + "fix_flow": { + "step": { + "confirm": { + "title": "[%key:component::tuya::issues::service_deprecation_turn_on::title%]", + "description": "Tuya vacuum support for the vacuum.turn_on service is deprecated and will be removed in Home Assistant 2024.2; Please adjust any automation or script that uses the service to instead call vacuum.start and select submit below to mark this issue as resolved." + } + } + } } } } From 30578d623655018805c5e97bf52e938a3843d115 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Tue, 11 Jul 2023 09:54:28 +0200 Subject: [PATCH 007/154] Deprecate mqtt vacuum with legacy schema (#95836) * Deprecate mqtt vacuum with legacy schema * Consistent comments * Correct comment * Remove persistence option * Adjust string, mention restart * Update deprecation comment --- homeassistant/components/mqtt/strings.json | 10 ++++ .../components/mqtt/vacuum/__init__.py | 50 +++++++++++++++++++ .../components/mqtt/vacuum/schema_legacy.py | 7 ++- tests/components/mqtt/test_legacy_vacuum.py | 29 +++++++++++ 4 files changed, 95 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/mqtt/strings.json b/homeassistant/components/mqtt/strings.json index c1eff29e3bef09..3423b2cd470102 100644 --- a/homeassistant/components/mqtt/strings.json +++ b/homeassistant/components/mqtt/strings.json @@ -1,4 +1,14 @@ { + "issues": { + "deprecation_mqtt_legacy_vacuum_yaml": { + "title": "MQTT vacuum entities with legacy schema found in your configuration.yaml", + "description": "MQTT vacuum entities that use the legacy schema are deprecated, please adjust your configuration.yaml and restart Home Assistant to fix this issue." + }, + "deprecation_mqtt_legacy_vacuum_discovery": { + "title": "MQTT vacuum entities with legacy schema added through MQTT discovery", + "description": "MQTT vacuum entities that use the legacy schema are deprecated, please adjust your devices to use the correct schema and restart Home Assistant to fix this issue." + } + }, "config": { "step": { "broker": { diff --git a/homeassistant/components/mqtt/vacuum/__init__.py b/homeassistant/components/mqtt/vacuum/__init__.py index 068bc183ec411c..3a2586bdfd7ce3 100644 --- a/homeassistant/components/mqtt/vacuum/__init__.py +++ b/homeassistant/components/mqtt/vacuum/__init__.py @@ -1,7 +1,12 @@ """Support for MQTT vacuums.""" + +# The legacy schema for MQTT vacuum was deprecated with HA Core 2023.8.0 +# and will be removed with HA Core 2024.2.0 + from __future__ import annotations import functools +import logging import voluptuous as vol @@ -9,8 +14,10 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType +from ..const import DOMAIN from ..mixins import async_setup_entry_helper from .schema import CONF_SCHEMA, LEGACY, MQTT_VACUUM_SCHEMA, STATE from .schema_legacy import ( @@ -24,9 +31,44 @@ async_setup_entity_state, ) +_LOGGER = logging.getLogger(__name__) + +MQTT_VACUUM_DOCS_URL = "https://www.home-assistant.io/integrations/vacuum.mqtt/" + + +# The legacy schema for MQTT vacuum was deprecated with HA Core 2023.8.0 +# and will be removed with HA Core 2024.2.0 +def warn_for_deprecation_legacy_schema( + hass: HomeAssistant, config: ConfigType, discovery_data: DiscoveryInfoType | None +) -> None: + """Warn for deprecation of legacy schema.""" + if config[CONF_SCHEMA] == STATE: + return + + key_suffix = "yaml" if discovery_data is None else "discovery" + translation_key = f"deprecation_mqtt_legacy_vacuum_{key_suffix}" + async_create_issue( + hass, + DOMAIN, + translation_key, + breaks_in_ha_version="2024.2.0", + is_fixable=False, + translation_key=translation_key, + learn_more_url=MQTT_VACUUM_DOCS_URL, + severity=IssueSeverity.WARNING, + ) + _LOGGER.warning( + "Deprecated `legacy` schema detected for MQTT vacuum, expected `state` schema, config found: %s", + config, + ) + def validate_mqtt_vacuum_discovery(config_value: ConfigType) -> ConfigType: """Validate MQTT vacuum schema.""" + + # The legacy schema for MQTT vacuum was deprecated with HA Core 2023.8.0 + # and will be removed with HA Core 2024.2.0 + schemas = {LEGACY: DISCOVERY_SCHEMA_LEGACY, STATE: DISCOVERY_SCHEMA_STATE} config: ConfigType = schemas[config_value[CONF_SCHEMA]](config_value) return config @@ -34,6 +76,10 @@ def validate_mqtt_vacuum_discovery(config_value: ConfigType) -> ConfigType: def validate_mqtt_vacuum_modern(config_value: ConfigType) -> ConfigType: """Validate MQTT vacuum modern schema.""" + + # The legacy schema for MQTT vacuum was deprecated with HA Core 2023.8.0 + # and will be removed with HA Core 2024.2.0 + schemas = { LEGACY: PLATFORM_SCHEMA_LEGACY_MODERN, STATE: PLATFORM_SCHEMA_STATE_MODERN, @@ -71,6 +117,10 @@ async def _async_setup_entity( discovery_data: DiscoveryInfoType | None = None, ) -> None: """Set up the MQTT vacuum.""" + + # The legacy schema for MQTT vacuum was deprecated with HA Core 2023.8.0 + # and will be removed with HA Core 2024.2.0 + warn_for_deprecation_legacy_schema(hass, config, discovery_data) setup_entity = { LEGACY: async_setup_entity_legacy, STATE: async_setup_entity_state, diff --git a/homeassistant/components/mqtt/vacuum/schema_legacy.py b/homeassistant/components/mqtt/vacuum/schema_legacy.py index 6cab62cdb5d0bb..18cda0b137d91a 100644 --- a/homeassistant/components/mqtt/vacuum/schema_legacy.py +++ b/homeassistant/components/mqtt/vacuum/schema_legacy.py @@ -1,4 +1,9 @@ -"""Support for Legacy MQTT vacuum.""" +"""Support for Legacy MQTT vacuum. + +The legacy schema for MQTT vacuum was deprecated with HA Core 2023.8.0 +and is will be removed with HA Core 2024.2.0 +""" + from __future__ import annotations from collections.abc import Callable diff --git a/tests/components/mqtt/test_legacy_vacuum.py b/tests/components/mqtt/test_legacy_vacuum.py index 9a71c747e65d73..8034d42ecbe94c 100644 --- a/tests/components/mqtt/test_legacy_vacuum.py +++ b/tests/components/mqtt/test_legacy_vacuum.py @@ -1,4 +1,8 @@ """The tests for the Legacy Mqtt vacuum platform.""" + +# The legacy schema for MQTT vacuum was deprecated with HA Core 2023.8.0 +# and will be removed with HA Core 2024.2.0 + from copy import deepcopy import json from typing import Any @@ -124,6 +128,31 @@ def vacuum_platform_only(): yield +@pytest.mark.parametrize( + ("hass_config", "deprecated"), + [ + ({mqtt.DOMAIN: {vacuum.DOMAIN: {"name": "test", "schema": "legacy"}}}, True), + ({mqtt.DOMAIN: {vacuum.DOMAIN: {"name": "test"}}}, True), + ({mqtt.DOMAIN: {vacuum.DOMAIN: {"name": "test", "schema": "state"}}}, False), + ], +) +async def test_deprecation( + hass: HomeAssistant, + mqtt_mock_entry: MqttMockHAClientGenerator, + caplog: pytest.LogCaptureFixture, + deprecated: bool, +) -> None: + """Test that the depration warning for the legacy schema works.""" + assert await mqtt_mock_entry() + entity = hass.states.get("vacuum.test") + assert entity is not None + + if deprecated: + assert "Deprecated `legacy` schema detected for MQTT vacuum" in caplog.text + else: + assert "Deprecated `legacy` schema detected for MQTT vacuum" not in caplog.text + + @pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG]) async def test_default_supported_features( hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator From beff19f93cefc3a21dc9d16cc401814fd6f0140b Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Tue, 11 Jul 2023 10:12:31 +0200 Subject: [PATCH 008/154] Improve mqtt tag schema logging and avoid tests that use xfail (#95711) Improve schema logging and tests --- homeassistant/components/mqtt/tag.py | 7 ++++- tests/components/mqtt/test_discovery.py | 2 -- tests/components/mqtt/test_init.py | 1 - tests/components/mqtt/test_tag.py | 38 ++++++++++++------------- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/homeassistant/components/mqtt/tag.py b/homeassistant/components/mqtt/tag.py index 02883b5cd8530e..848950169d8dde 100644 --- a/homeassistant/components/mqtt/tag.py +++ b/homeassistant/components/mqtt/tag.py @@ -20,6 +20,7 @@ from .mixins import ( MQTT_ENTITY_DEVICE_INFO_SCHEMA, MqttDiscoveryDeviceUpdate, + async_handle_schema_error, async_setup_entry_helper, send_discovery_done, update_device, @@ -119,7 +120,11 @@ def __init__( async def async_update(self, discovery_data: MQTTDiscoveryPayload) -> None: """Handle MQTT tag discovery updates.""" # Update tag scanner - config: DiscoveryInfoType = PLATFORM_SCHEMA(discovery_data) + try: + config: DiscoveryInfoType = PLATFORM_SCHEMA(discovery_data) + except vol.Invalid as err: + async_handle_schema_error(discovery_data, err) + return self._config = config self._value_template = MqttValueTemplate( config.get(CONF_VALUE_TEMPLATE), diff --git a/tests/components/mqtt/test_discovery.py b/tests/components/mqtt/test_discovery.py index f35af9fb0378ea..14074ce113546a 100644 --- a/tests/components/mqtt/test_discovery.py +++ b/tests/components/mqtt/test_discovery.py @@ -7,7 +7,6 @@ from unittest.mock import AsyncMock, call, patch import pytest -from voluptuous import MultipleInvalid from homeassistant import config_entries from homeassistant.components import mqtt @@ -1643,7 +1642,6 @@ async def test_unique_id_collission_has_priority( assert entity_registry.async_get("sensor.sbfspot_12345_2") is None -@pytest.mark.xfail(raises=MultipleInvalid) @patch("homeassistant.components.mqtt.PLATFORMS", [Platform.SENSOR]) async def test_update_with_bad_config_not_breaks_discovery( hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator diff --git a/tests/components/mqtt/test_init.py b/tests/components/mqtt/test_init.py index eee1d00613732e..08aa53aec7a1b5 100644 --- a/tests/components/mqtt/test_init.py +++ b/tests/components/mqtt/test_init.py @@ -2096,7 +2096,6 @@ async def test_setup_manual_mqtt_with_platform_key( @pytest.mark.parametrize("hass_config", [{mqtt.DOMAIN: {"light": {"name": "test"}}}]) -@pytest.mark.xfail(reason="Invalid config for [mqtt]: required key not provided") @patch("homeassistant.components.mqtt.PLATFORMS", []) async def test_setup_manual_mqtt_with_invalid_config( hass: HomeAssistant, diff --git a/tests/components/mqtt/test_tag.py b/tests/components/mqtt/test_tag.py index f8c7b55f7ce01f..c18e24d1a701b5 100644 --- a/tests/components/mqtt/test_tag.py +++ b/tests/components/mqtt/test_tag.py @@ -1,10 +1,10 @@ """The tests for MQTT tag scanner.""" +from collections.abc import Generator import copy import json -from unittest.mock import ANY, patch +from unittest.mock import ANY, AsyncMock, patch import pytest -from voluptuous import MultipleInvalid from homeassistant.components.device_automation import DeviceAutomationType from homeassistant.components.mqtt.const import DOMAIN as MQTT_DOMAIN @@ -47,14 +47,14 @@ @pytest.fixture(autouse=True) -def binary_sensor_only(): +def binary_sensor_only() -> Generator[None, None, None]: """Only setup the binary_sensor platform to speed up test.""" with patch("homeassistant.components.mqtt.PLATFORMS", [Platform.BINARY_SENSOR]): yield @pytest.fixture -def tag_mock(): +def tag_mock() -> Generator[AsyncMock, None, None]: """Fixture to mock tag.""" with patch("homeassistant.components.tag.async_scan_tag") as mock_tag: yield mock_tag @@ -65,7 +65,7 @@ async def test_discover_bad_tag( hass: HomeAssistant, device_registry: dr.DeviceRegistry, mqtt_mock_entry: MqttMockHAClientGenerator, - tag_mock, + tag_mock: AsyncMock, ) -> None: """Test bad discovery message.""" await mqtt_mock_entry() @@ -92,7 +92,7 @@ async def test_if_fires_on_mqtt_message_with_device( hass: HomeAssistant, device_registry: dr.DeviceRegistry, mqtt_mock_entry: MqttMockHAClientGenerator, - tag_mock, + tag_mock: AsyncMock, ) -> None: """Test tag scanning, with device.""" await mqtt_mock_entry() @@ -110,9 +110,8 @@ async def test_if_fires_on_mqtt_message_with_device( async def test_if_fires_on_mqtt_message_without_device( hass: HomeAssistant, - device_registry: dr.DeviceRegistry, mqtt_mock_entry: MqttMockHAClientGenerator, - tag_mock, + tag_mock: AsyncMock, ) -> None: """Test tag scanning, without device.""" await mqtt_mock_entry() @@ -131,7 +130,7 @@ async def test_if_fires_on_mqtt_message_with_template( hass: HomeAssistant, device_registry: dr.DeviceRegistry, mqtt_mock_entry: MqttMockHAClientGenerator, - tag_mock, + tag_mock: AsyncMock, ) -> None: """Test tag scanning, with device.""" await mqtt_mock_entry() @@ -150,7 +149,7 @@ async def test_if_fires_on_mqtt_message_with_template( async def test_strip_tag_id( hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator, - tag_mock, + tag_mock: AsyncMock, ) -> None: """Test strip whitespace from tag_id.""" await mqtt_mock_entry() @@ -169,7 +168,7 @@ async def test_if_fires_on_mqtt_message_after_update_with_device( hass: HomeAssistant, device_registry: dr.DeviceRegistry, mqtt_mock_entry: MqttMockHAClientGenerator, - tag_mock, + tag_mock: AsyncMock, ) -> None: """Test tag scanning after update.""" await mqtt_mock_entry() @@ -218,7 +217,7 @@ async def test_if_fires_on_mqtt_message_after_update_with_device( async def test_if_fires_on_mqtt_message_after_update_without_device( hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator, - tag_mock, + tag_mock: AsyncMock, ) -> None: """Test tag scanning after update.""" await mqtt_mock_entry() @@ -265,7 +264,7 @@ async def test_if_fires_on_mqtt_message_after_update_with_template( hass: HomeAssistant, device_registry: dr.DeviceRegistry, mqtt_mock_entry: MqttMockHAClientGenerator, - tag_mock, + tag_mock: AsyncMock, ) -> None: """Test tag scanning after update.""" await mqtt_mock_entry() @@ -333,7 +332,7 @@ async def test_not_fires_on_mqtt_message_after_remove_by_mqtt_with_device( hass: HomeAssistant, device_registry: dr.DeviceRegistry, mqtt_mock_entry: MqttMockHAClientGenerator, - tag_mock, + tag_mock: AsyncMock, ) -> None: """Test tag scanning after removal.""" await mqtt_mock_entry() @@ -369,7 +368,7 @@ async def test_not_fires_on_mqtt_message_after_remove_by_mqtt_with_device( async def test_not_fires_on_mqtt_message_after_remove_by_mqtt_without_device( hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator, - tag_mock, + tag_mock: AsyncMock, ) -> None: """Test tag scanning not firing after removal.""" await mqtt_mock_entry() @@ -406,7 +405,7 @@ async def test_not_fires_on_mqtt_message_after_remove_from_registry( hass_ws_client: WebSocketGenerator, device_registry: dr.DeviceRegistry, mqtt_mock_entry: MqttMockHAClientGenerator, - tag_mock, + tag_mock: AsyncMock, ) -> None: """Test tag scanning after removal.""" assert await async_setup_component(hass, "config", {}) @@ -843,11 +842,11 @@ async def test_cleanup_device_with_entity2( assert device_entry is None -@pytest.mark.xfail(raises=MultipleInvalid) async def test_update_with_bad_config_not_breaks_discovery( hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator, - tag_mock, + caplog: pytest.LogCaptureFixture, + tag_mock: AsyncMock, ) -> None: """Test a bad update does not break discovery.""" await mqtt_mock_entry() @@ -875,6 +874,7 @@ async def test_update_with_bad_config_not_breaks_discovery( # Update with bad identifier async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", data2) await hass.async_block_till_done() + assert "extra keys not allowed @ data['device']['bad_key']" in caplog.text # Topic update async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", data3) @@ -891,7 +891,7 @@ async def test_unload_entry( hass: HomeAssistant, device_registry: dr.DeviceRegistry, mqtt_mock: MqttMockHAClient, - tag_mock, + tag_mock: AsyncMock, ) -> None: """Test unloading the MQTT entry.""" From f3e55e96f442c6d5d8cbfd258e49b0c1a8535257 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Tue, 11 Jul 2023 10:16:00 +0200 Subject: [PATCH 009/154] Improve test coverage mqtt vacuum (#96288) --- tests/components/mqtt/test_legacy_vacuum.py | 35 ++++++++++++++++++ tests/components/mqtt/test_state_vacuum.py | 40 ++++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/tests/components/mqtt/test_legacy_vacuum.py b/tests/components/mqtt/test_legacy_vacuum.py index 8034d42ecbe94c..6b1a74f256dcca 100644 --- a/tests/components/mqtt/test_legacy_vacuum.py +++ b/tests/components/mqtt/test_legacy_vacuum.py @@ -321,6 +321,41 @@ async def test_commands_without_supported_features( mqtt_mock.async_publish.reset_mock() +@pytest.mark.parametrize( + "hass_config", + [ + { + "mqtt": { + "vacuum": { + "name": "test", + "schema": "legacy", + mqttvacuum.CONF_SUPPORTED_FEATURES: services_to_strings( + ALL_SERVICES, SERVICE_TO_STRING + ), + } + } + } + ], +) +async def test_command_without_command_topic( + hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator +) -> None: + """Test commands which are not supported by the vacuum.""" + mqtt_mock = await mqtt_mock_entry() + + await common.async_turn_on(hass, "vacuum.test") + mqtt_mock.async_publish.assert_not_called() + mqtt_mock.async_publish.reset_mock() + + await common.async_set_fan_speed(hass, "low", "vacuum.test") + mqtt_mock.async_publish.assert_not_called() + mqtt_mock.async_publish.reset_mock() + + await common.async_send_command(hass, "some command", "vacuum.test") + mqtt_mock.async_publish.assert_not_called() + mqtt_mock.async_publish.reset_mock() + + @pytest.mark.parametrize( "hass_config", [ diff --git a/tests/components/mqtt/test_state_vacuum.py b/tests/components/mqtt/test_state_vacuum.py index 38baf591094d34..b22fb96aa13706 100644 --- a/tests/components/mqtt/test_state_vacuum.py +++ b/tests/components/mqtt/test_state_vacuum.py @@ -11,7 +11,10 @@ from homeassistant.components.mqtt.vacuum import CONF_SCHEMA, schema_state as mqttvacuum from homeassistant.components.mqtt.vacuum.const import MQTT_VACUUM_ATTRIBUTES_BLOCKED from homeassistant.components.mqtt.vacuum.schema import services_to_strings -from homeassistant.components.mqtt.vacuum.schema_state import SERVICE_TO_STRING +from homeassistant.components.mqtt.vacuum.schema_state import ( + ALL_SERVICES, + SERVICE_TO_STRING, +) from homeassistant.components.vacuum import ( ATTR_BATTERY_ICON, ATTR_BATTERY_LEVEL, @@ -255,6 +258,41 @@ async def test_commands_without_supported_features( mqtt_mock.async_publish.assert_not_called() +@pytest.mark.parametrize( + "hass_config", + [ + { + "mqtt": { + "vacuum": { + "name": "test", + "schema": "state", + mqttvacuum.CONF_SUPPORTED_FEATURES: services_to_strings( + ALL_SERVICES, SERVICE_TO_STRING + ), + } + } + } + ], +) +async def test_command_without_command_topic( + hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator +) -> None: + """Test commands which are not supported by the vacuum.""" + mqtt_mock = await mqtt_mock_entry() + + await common.async_start(hass, "vacuum.test") + mqtt_mock.async_publish.assert_not_called() + mqtt_mock.async_publish.reset_mock() + + await common.async_set_fan_speed(hass, "low", "vacuum.test") + mqtt_mock.async_publish.assert_not_called() + mqtt_mock.async_publish.reset_mock() + + await common.async_send_command(hass, "some command", "vacuum.test") + mqtt_mock.async_publish.assert_not_called() + mqtt_mock.async_publish.reset_mock() + + @pytest.mark.parametrize("hass_config", [CONFIG_ALL_SERVICES]) async def test_status( hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator From f46188c85a3fecdacf6cf5de09c3127ae4bfe9f1 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 11 Jul 2023 11:34:16 +0200 Subject: [PATCH 010/154] Improve the docstring of some config schema generators (#96296) --- homeassistant/helpers/config_validation.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/homeassistant/helpers/config_validation.py b/homeassistant/helpers/config_validation.py index e8f1e58615cfe3..90aa499af4bab8 100644 --- a/homeassistant/helpers/config_validation.py +++ b/homeassistant/helpers/config_validation.py @@ -1127,7 +1127,11 @@ def validator(config: dict) -> dict: def config_entry_only_config_schema(domain: str) -> Callable[[dict], dict]: - """Return a config schema which logs if attempted to setup from YAML.""" + """Return a config schema which logs if attempted to setup from YAML. + + Use this when an integration's __init__.py defines setup or async_setup + but setup from yaml is not supported. + """ return _no_yaml_config_schema( domain, @@ -1138,7 +1142,11 @@ def config_entry_only_config_schema(domain: str) -> Callable[[dict], dict]: def platform_only_config_schema(domain: str) -> Callable[[dict], dict]: - """Return a config schema which logs if attempted to setup from YAML.""" + """Return a config schema which logs if attempted to setup from YAML. + + Use this when an integration's __init__.py defines setup or async_setup + but setup from the integration key is not supported. + """ return _no_yaml_config_schema( domain, From d4089bbdbe9c2de67e083aa25498f931b9579a69 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 11 Jul 2023 01:29:05 -1000 Subject: [PATCH 011/154] Bump aiohomekit to 2.6.7 (#96291) --- homeassistant/components/homekit_controller/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/homekit_controller/manifest.json b/homeassistant/components/homekit_controller/manifest.json index d0a88bf8249afc..2a9e2225e9f3be 100644 --- a/homeassistant/components/homekit_controller/manifest.json +++ b/homeassistant/components/homekit_controller/manifest.json @@ -14,6 +14,6 @@ "documentation": "https://www.home-assistant.io/integrations/homekit_controller", "iot_class": "local_push", "loggers": ["aiohomekit", "commentjson"], - "requirements": ["aiohomekit==2.6.5"], + "requirements": ["aiohomekit==2.6.7"], "zeroconf": ["_hap._tcp.local.", "_hap._udp.local."] } diff --git a/requirements_all.txt b/requirements_all.txt index 44d3f4834f8183..e5013b24ce67a1 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -249,7 +249,7 @@ aioguardian==2022.07.0 aioharmony==0.2.10 # homeassistant.components.homekit_controller -aiohomekit==2.6.5 +aiohomekit==2.6.7 # homeassistant.components.emulated_hue # homeassistant.components.http diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 0e6a806518e4f8..13586bf8f262c7 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -227,7 +227,7 @@ aioguardian==2022.07.0 aioharmony==0.2.10 # homeassistant.components.homekit_controller -aiohomekit==2.6.5 +aiohomekit==2.6.7 # homeassistant.components.emulated_hue # homeassistant.components.http From d9f27400b7981ce13259de5007159e635238a87d Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Tue, 11 Jul 2023 14:10:32 +0200 Subject: [PATCH 012/154] Reolink add reboot button (#96311) --- homeassistant/components/reolink/button.py | 70 ++++++++++++++++++++-- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/reolink/button.py b/homeassistant/components/reolink/button.py index 3aa5faa527b096..7a6e2486c71c9d 100644 --- a/homeassistant/components/reolink/button.py +++ b/homeassistant/components/reolink/button.py @@ -7,7 +7,11 @@ from reolink_aio.api import GuardEnum, Host, PtzEnum -from homeassistant.components.button import ButtonEntity, ButtonEntityDescription +from homeassistant.components.button import ( + ButtonDeviceClass, + ButtonEntity, + ButtonEntityDescription, +) from homeassistant.config_entries import ConfigEntry from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant @@ -15,12 +19,12 @@ from . import ReolinkData from .const import DOMAIN -from .entity import ReolinkChannelCoordinatorEntity +from .entity import ReolinkChannelCoordinatorEntity, ReolinkHostCoordinatorEntity @dataclass class ReolinkButtonEntityDescriptionMixin: - """Mixin values for Reolink button entities.""" + """Mixin values for Reolink button entities for a camera channel.""" method: Callable[[Host, int], Any] @@ -29,11 +33,27 @@ class ReolinkButtonEntityDescriptionMixin: class ReolinkButtonEntityDescription( ButtonEntityDescription, ReolinkButtonEntityDescriptionMixin ): - """A class that describes button entities.""" + """A class that describes button entities for a camera channel.""" supported: Callable[[Host, int], bool] = lambda api, ch: True +@dataclass +class ReolinkHostButtonEntityDescriptionMixin: + """Mixin values for Reolink button entities for the host.""" + + method: Callable[[Host], Any] + + +@dataclass +class ReolinkHostButtonEntityDescription( + ButtonEntityDescription, ReolinkHostButtonEntityDescriptionMixin +): + """A class that describes button entities for the host.""" + + supported: Callable[[Host], bool] = lambda api: True + + BUTTON_ENTITIES = ( ReolinkButtonEntityDescription( key="ptz_stop", @@ -95,6 +115,17 @@ class ReolinkButtonEntityDescription( ), ) +HOST_BUTTON_ENTITIES = ( + ReolinkHostButtonEntityDescription( + key="reboot", + device_class=ButtonDeviceClass.RESTART, + entity_category=EntityCategory.CONFIG, + entity_registry_enabled_default=False, + supported=lambda api: api.supported(None, "reboot"), + method=lambda api: api.reboot(), + ), +) + async def async_setup_entry( hass: HomeAssistant, @@ -104,12 +135,20 @@ async def async_setup_entry( """Set up a Reolink button entities.""" reolink_data: ReolinkData = hass.data[DOMAIN][config_entry.entry_id] - async_add_entities( + entities: list[ReolinkButtonEntity | ReolinkHostButtonEntity] = [ ReolinkButtonEntity(reolink_data, channel, entity_description) for entity_description in BUTTON_ENTITIES for channel in reolink_data.host.api.channels if entity_description.supported(reolink_data.host.api, channel) + ] + entities.extend( + [ + ReolinkHostButtonEntity(reolink_data, entity_description) + for entity_description in HOST_BUTTON_ENTITIES + if entity_description.supported(reolink_data.host.api) + ] ) + async_add_entities(entities) class ReolinkButtonEntity(ReolinkChannelCoordinatorEntity, ButtonEntity): @@ -134,3 +173,24 @@ def __init__( async def async_press(self) -> None: """Execute the button action.""" await self.entity_description.method(self._host.api, self._channel) + + +class ReolinkHostButtonEntity(ReolinkHostCoordinatorEntity, ButtonEntity): + """Base button entity class for Reolink IP cameras.""" + + entity_description: ReolinkHostButtonEntityDescription + + def __init__( + self, + reolink_data: ReolinkData, + entity_description: ReolinkHostButtonEntityDescription, + ) -> None: + """Initialize Reolink button entity.""" + super().__init__(reolink_data) + self.entity_description = entity_description + + self._attr_unique_id = f"{self._host.unique_id}_{entity_description.key}" + + async def async_press(self) -> None: + """Execute the button action.""" + await self.entity_description.method(self._host.api) From f12f8bca0355e4b02797aa9e4f477d8ad5fe1c44 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Tue, 11 Jul 2023 15:27:31 +0200 Subject: [PATCH 013/154] Avoid CI fail in command_line tests (#96324) * Avoid CI fail in command_line tests * Speedup tests manual update --- .../command_line/test_binary_sensor.py | 19 +++++++++---------- tests/components/command_line/test_cover.py | 19 +++++++++---------- tests/components/command_line/test_sensor.py | 17 ++++++++--------- tests/components/command_line/test_switch.py | 17 ++++++++--------- 4 files changed, 34 insertions(+), 38 deletions(-) diff --git a/tests/components/command_line/test_binary_sensor.py b/tests/components/command_line/test_binary_sensor.py index 9e97f053e07778..910288d6920cae 100644 --- a/tests/components/command_line/test_binary_sensor.py +++ b/tests/components/command_line/test_binary_sensor.py @@ -240,16 +240,18 @@ async def _async_update(self) -> None: ) await hass.async_block_till_done() - assert len(called) == 1 + assert called assert ( "Updating Command Line Binary Sensor Test took longer than the scheduled update interval" not in caplog.text ) + called.clear() + caplog.clear() async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=1)) await hass.async_block_till_done() - assert len(called) == 2 + assert called assert ( "Updating Command Line Binary Sensor Test took longer than the scheduled update interval" in caplog.text @@ -266,13 +268,11 @@ async def test_updating_manually( called = [] class MockCommandBinarySensor(CommandBinarySensor): - """Mock entity that updates slow.""" + """Mock entity that updates.""" async def _async_update(self) -> None: - """Update slow.""" + """Update.""" called.append(1) - # Add waiting time - await asyncio.sleep(1) with patch( "homeassistant.components.command_line.binary_sensor.CommandBinarySensor", @@ -297,7 +297,8 @@ async def _async_update(self) -> None: ) await hass.async_block_till_done() - assert len(called) == 1 + assert called + called.clear await hass.services.async_call( HA_DOMAIN, @@ -306,6 +307,4 @@ async def _async_update(self) -> None: blocking=True, ) await hass.async_block_till_done() - assert len(called) == 2 - - await asyncio.sleep(0.2) + assert called diff --git a/tests/components/command_line/test_cover.py b/tests/components/command_line/test_cover.py index ac0a33fc7a979c..d4114f9bbbd787 100644 --- a/tests/components/command_line/test_cover.py +++ b/tests/components/command_line/test_cover.py @@ -326,16 +326,18 @@ async def _async_update(self) -> None: ) await hass.async_block_till_done() - assert len(called) == 0 + assert not called assert ( "Updating Command Line Cover Test took longer than the scheduled update interval" not in caplog.text ) + called.clear() + caplog.clear() async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=1)) await hass.async_block_till_done() - assert len(called) == 1 + assert called assert ( "Updating Command Line Cover Test took longer than the scheduled update interval" in caplog.text @@ -352,13 +354,11 @@ async def test_updating_manually( called = [] class MockCommandCover(CommandCover): - """Mock entity that updates slow.""" + """Mock entity that updates.""" async def _async_update(self) -> None: - """Update slow.""" + """Update.""" called.append(1) - # Add waiting time - await asyncio.sleep(1) with patch( "homeassistant.components.command_line.cover.CommandCover", @@ -384,7 +384,8 @@ async def _async_update(self) -> None: async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=10)) await hass.async_block_till_done() - assert len(called) == 1 + assert called + called.clear() await hass.services.async_call( HA_DOMAIN, @@ -393,6 +394,4 @@ async def _async_update(self) -> None: blocking=True, ) await hass.async_block_till_done() - assert len(called) == 2 - - await asyncio.sleep(0.2) + assert called diff --git a/tests/components/command_line/test_sensor.py b/tests/components/command_line/test_sensor.py index b837f5808622c6..af7bf3222a14bd 100644 --- a/tests/components/command_line/test_sensor.py +++ b/tests/components/command_line/test_sensor.py @@ -575,16 +575,18 @@ async def _async_update(self) -> None: ) await hass.async_block_till_done() - assert len(called) == 1 + assert called assert ( "Updating Command Line Sensor Test took longer than the scheduled update interval" not in caplog.text ) + called.clear() + caplog.clear() async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=1)) await hass.async_block_till_done() - assert len(called) == 2 + assert called assert ( "Updating Command Line Sensor Test took longer than the scheduled update interval" in caplog.text @@ -601,13 +603,11 @@ async def test_updating_manually( called = [] class MockCommandSensor(CommandSensor): - """Mock entity that updates slow.""" + """Mock entity that updates.""" async def _async_update(self) -> None: """Update slow.""" called.append(1) - # Add waiting time - await asyncio.sleep(1) with patch( "homeassistant.components.command_line.sensor.CommandSensor", @@ -630,7 +630,8 @@ async def _async_update(self) -> None: ) await hass.async_block_till_done() - assert len(called) == 1 + assert called + called.clear() await hass.services.async_call( HA_DOMAIN, @@ -639,6 +640,4 @@ async def _async_update(self) -> None: blocking=True, ) await hass.async_block_till_done() - assert len(called) == 2 - - await asyncio.sleep(0.2) + assert called diff --git a/tests/components/command_line/test_switch.py b/tests/components/command_line/test_switch.py index e5331fbe7dda69..12a037f0dd115e 100644 --- a/tests/components/command_line/test_switch.py +++ b/tests/components/command_line/test_switch.py @@ -684,16 +684,18 @@ async def _async_update(self) -> None: ) await hass.async_block_till_done() - assert len(called) == 0 + assert not called assert ( "Updating Command Line Switch Test took longer than the scheduled update interval" not in caplog.text ) + called.clear() + caplog.clear() async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=1)) await hass.async_block_till_done() - assert len(called) == 1 + assert called assert ( "Updating Command Line Switch Test took longer than the scheduled update interval" in caplog.text @@ -710,13 +712,11 @@ async def test_updating_manually( called = [] class MockCommandSwitch(CommandSwitch): - """Mock entity that updates slow.""" + """Mock entity that updates.""" async def _async_update(self) -> None: """Update slow.""" called.append(1) - # Add waiting time - await asyncio.sleep(1) with patch( "homeassistant.components.command_line.switch.CommandSwitch", @@ -743,7 +743,8 @@ async def _async_update(self) -> None: async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=10)) await hass.async_block_till_done() - assert len(called) == 1 + assert called + called.clear() await hass.services.async_call( HA_DOMAIN, @@ -752,6 +753,4 @@ async def _async_update(self) -> None: blocking=True, ) await hass.async_block_till_done() - assert len(called) == 2 - - await asyncio.sleep(0.2) + assert called From f054de0ad5d60bcec27de7771dc19c18e40a314b Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 15:52:12 +0200 Subject: [PATCH 014/154] Add support for service translations (#95984) --- homeassistant/components/light/services.yaml | 84 +----- homeassistant/components/light/strings.json | 302 +++++++++++++++++++ homeassistant/helpers/service.py | 85 ++++-- homeassistant/helpers/translation.py | 2 +- script/hassfest/services.py | 72 ++++- script/hassfest/translations.py | 14 + tests/helpers/test_service.py | 45 ++- 7 files changed, 484 insertions(+), 120 deletions(-) diff --git a/homeassistant/components/light/services.yaml b/homeassistant/components/light/services.yaml index d1221dd121071e..1ba204e5eda900 100644 --- a/homeassistant/components/light/services.yaml +++ b/homeassistant/components/light/services.yaml @@ -1,17 +1,11 @@ # Describes the format for available light services turn_on: - name: Turn on - description: > - Turn on one or more lights and adjust properties of the light, even when - they are turned on already. target: entity: domain: light fields: transition: - name: Transition - description: Duration it takes to get to next state. filter: supported_features: - light.LightEntityFeature.TRANSITION @@ -21,8 +15,6 @@ turn_on: max: 300 unit_of_measurement: seconds rgb_color: - name: Color - description: The color for the light (based on RGB - red, green, blue). filter: attribute: supported_color_modes: @@ -34,8 +26,6 @@ turn_on: selector: color_rgb: rgbw_color: - name: RGBW-color - description: A list containing four integers between 0 and 255 representing the RGBW (red, green, blue, white) color for the light. filter: attribute: supported_color_modes: @@ -49,8 +39,6 @@ turn_on: selector: object: rgbww_color: - name: RGBWW-color - description: A list containing five integers between 0 and 255 representing the RGBWW (red, green, blue, cold white, warm white) color for the light. filter: attribute: supported_color_modes: @@ -64,8 +52,6 @@ turn_on: selector: object: color_name: - name: Color name - description: A human readable color name. filter: attribute: supported_color_modes: @@ -77,6 +63,7 @@ turn_on: advanced: true selector: select: + translation_key: color_name options: - "homeassistant" - "aliceblue" @@ -228,8 +215,6 @@ turn_on: - "yellow" - "yellowgreen" hs_color: - name: Hue/Sat color - description: Color for the light in hue/sat format. Hue is 0-360 and Sat is 0-100. filter: attribute: supported_color_modes: @@ -243,8 +228,6 @@ turn_on: selector: object: xy_color: - name: XY-color - description: Color for the light in XY-format. filter: attribute: supported_color_modes: @@ -258,8 +241,6 @@ turn_on: selector: object: color_temp: - name: Color temperature - description: Color temperature for the light in mireds. filter: attribute: supported_color_modes: @@ -274,8 +255,6 @@ turn_on: min_mireds: 153 max_mireds: 500 kelvin: - name: Color temperature (Kelvin) - description: Color temperature for the light in Kelvin. filter: attribute: supported_color_modes: @@ -293,10 +272,6 @@ turn_on: step: 100 unit_of_measurement: K brightness: - name: Brightness value - description: Number indicating brightness, where 0 turns the light - off, 1 is the minimum brightness and 255 is the maximum brightness - supported by the light. filter: attribute: supported_color_modes: @@ -313,10 +288,6 @@ turn_on: min: 0 max: 255 brightness_pct: - name: Brightness - description: Number indicating percentage of full brightness, where 0 - turns the light off, 1 is the minimum brightness and 100 is the maximum - brightness supported by the light. filter: attribute: supported_color_modes: @@ -333,8 +304,6 @@ turn_on: max: 100 unit_of_measurement: "%" brightness_step: - name: Brightness step value - description: Change brightness by an amount. filter: attribute: supported_color_modes: @@ -351,8 +320,6 @@ turn_on: min: -225 max: 255 brightness_step_pct: - name: Brightness step - description: Change brightness by a percentage. filter: attribute: supported_color_modes: @@ -369,8 +336,6 @@ turn_on: max: 100 unit_of_measurement: "%" white: - name: White - description: Set the light to white mode. filter: attribute: supported_color_modes: @@ -381,15 +346,11 @@ turn_on: value: true label: Enabled profile: - name: Profile - description: Name of a light profile to use. advanced: true example: relax selector: text: flash: - name: Flash - description: If the light should flash. filter: supported_features: - light.LightEntityFeature.FLASH @@ -402,8 +363,6 @@ turn_on: - label: "Short" value: "short" effect: - name: Effect - description: Light effect. filter: supported_features: - light.LightEntityFeature.EFFECT @@ -411,15 +370,11 @@ turn_on: text: turn_off: - name: Turn off - description: Turns off one or more lights. target: entity: domain: light fields: transition: - name: Transition - description: Duration it takes to get to next state. filter: supported_features: - light.LightEntityFeature.TRANSITION @@ -429,8 +384,6 @@ turn_off: max: 300 unit_of_measurement: seconds flash: - name: Flash - description: If the light should flash. filter: supported_features: - light.LightEntityFeature.FLASH @@ -444,17 +397,11 @@ turn_off: value: "short" toggle: - name: Toggle - description: > - Toggles one or more lights, from on to off, or, off to on, based on their - current state. target: entity: domain: light fields: transition: - name: Transition - description: Duration it takes to get to next state. filter: supported_features: - light.LightEntityFeature.TRANSITION @@ -464,8 +411,6 @@ toggle: max: 300 unit_of_measurement: seconds rgb_color: - name: RGB-color - description: Color for the light in RGB-format. filter: attribute: supported_color_modes: @@ -479,8 +424,6 @@ toggle: selector: object: color_name: - name: Color name - description: A human readable color name. filter: attribute: supported_color_modes: @@ -492,6 +435,7 @@ toggle: advanced: true selector: select: + translation_key: color_name options: - "homeassistant" - "aliceblue" @@ -643,8 +587,6 @@ toggle: - "yellow" - "yellowgreen" hs_color: - name: Hue/Sat color - description: Color for the light in hue/sat format. Hue is 0-360 and Sat is 0-100. filter: attribute: supported_color_modes: @@ -658,8 +600,6 @@ toggle: selector: object: xy_color: - name: XY-color - description: Color for the light in XY-format. filter: attribute: supported_color_modes: @@ -673,8 +613,6 @@ toggle: selector: object: color_temp: - name: Color temperature (mireds) - description: Color temperature for the light in mireds. filter: attribute: supported_color_modes: @@ -688,8 +626,6 @@ toggle: selector: color_temp: kelvin: - name: Color temperature (Kelvin) - description: Color temperature for the light in Kelvin. filter: attribute: supported_color_modes: @@ -707,10 +643,6 @@ toggle: step: 100 unit_of_measurement: K brightness: - name: Brightness value - description: Number indicating brightness, where 0 turns the light - off, 1 is the minimum brightness and 255 is the maximum brightness - supported by the light. filter: attribute: supported_color_modes: @@ -727,10 +659,6 @@ toggle: min: 0 max: 255 brightness_pct: - name: Brightness - description: Number indicating percentage of full brightness, where 0 - turns the light off, 1 is the minimum brightness and 100 is the maximum - brightness supported by the light. filter: attribute: supported_color_modes: @@ -747,8 +675,6 @@ toggle: max: 100 unit_of_measurement: "%" white: - name: White - description: Set the light to white mode. filter: attribute: supported_color_modes: @@ -759,15 +685,11 @@ toggle: value: true label: Enabled profile: - name: Profile - description: Name of a light profile to use. advanced: true example: relax selector: text: flash: - name: Flash - description: If the light should flash. filter: supported_features: - light.LightEntityFeature.FLASH @@ -780,8 +702,6 @@ toggle: - label: "Short" value: "short" effect: - name: Effect - description: Light effect. filter: supported_features: - light.LightEntityFeature.EFFECT diff --git a/homeassistant/components/light/strings.json b/homeassistant/components/light/strings.json index 6219ade3e58384..a4a46d2ca94140 100644 --- a/homeassistant/components/light/strings.json +++ b/homeassistant/components/light/strings.json @@ -86,5 +86,307 @@ } } } + }, + "selector": { + "color_name": { + "options": { + "homeassistant": "Home Assistant", + "aliceblue": "Alice blue", + "antiquewhite": "Antique white", + "aqua": "Aqua", + "aquamarine": "Aquamarine", + "azure": "Azure", + "beige": "Beige", + "bisque": "Bisque", + "blanchedalmond": "Blanched almond", + "blue": "Blue", + "blueviolet": "Blue violet", + "brown": "Brown", + "burlywood": "Burlywood", + "cadetblue": "Cadet blue", + "chartreuse": "Chartreuse", + "chocolate": "Chocolate", + "coral": "Coral", + "cornflowerblue": "Cornflower blue", + "cornsilk": "Cornsilk", + "crimson": "Crimson", + "cyan": "Cyan", + "darkblue": "Dark blue", + "darkcyan": "Dark cyan", + "darkgoldenrod": "Dark goldenrod", + "darkgray": "Dark gray", + "darkgreen": "Dark green", + "darkgrey": "Dark grey", + "darkkhaki": "Dark khaki", + "darkmagenta": "Dark magenta", + "darkolivegreen": "Dark olive green", + "darkorange": "Dark orange", + "darkorchid": "Dark orchid", + "darkred": "Dark red", + "darksalmon": "Dark salmon", + "darkseagreen": "Dark sea green", + "darkslateblue": "Dark slate blue", + "darkslategray": "Dark slate gray", + "darkslategrey": "Dark slate grey", + "darkturquoise": "Dark turquoise", + "darkviolet": "Dark violet", + "deeppink": "Deep pink", + "deepskyblue": "Deep sky blue", + "dimgray": "Dim gray", + "dimgrey": "Dim grey", + "dodgerblue": "Dodger blue", + "firebrick": "Fire brick", + "floralwhite": "Floral white", + "forestgreen": "Forest green", + "fuchsia": "Fuchsia", + "gainsboro": "Gainsboro", + "ghostwhite": "Ghost white", + "gold": "Gold", + "goldenrod": "Goldenrod", + "gray": "Gray", + "green": "Green", + "greenyellow": "Green yellow", + "grey": "Grey", + "honeydew": "Honeydew", + "hotpink": "Hot pink", + "indianred": "Indian red", + "indigo": "Indigo", + "ivory": "Ivory", + "khaki": "Khaki", + "lavender": "Lavender", + "lavenderblush": "Lavender blush", + "lawngreen": "Lawn green", + "lemonchiffon": "Lemon chiffon", + "lightblue": "Light blue", + "lightcoral": "Light coral", + "lightcyan": "Light cyan", + "lightgoldenrodyellow": "Light goldenrod yellow", + "lightgray": "Light gray", + "lightgreen": "Light green", + "lightgrey": "Light grey", + "lightpink": "Light pink", + "lightsalmon": "Light salmon", + "lightseagreen": "Light sea green", + "lightskyblue": "Light sky blue", + "lightslategray": "Light slate gray", + "lightslategrey": "Light slate grey", + "lightsteelblue": "Light steel blue", + "lightyellow": "Light yellow", + "lime": "Lime", + "limegreen": "Lime green", + "linen": "Linen", + "magenta": "Magenta", + "maroon": "Maroon", + "mediumaquamarine": "Medium aquamarine", + "mediumblue": "Medium blue", + "mediumorchid": "Medium orchid", + "mediumpurple": "Medium purple", + "mediumseagreen": "Medium sea green", + "mediumslateblue": "Medium slate blue", + "mediumspringgreen": "Medium spring green", + "mediumturquoise": "Medium turquoise", + "mediumvioletred": "Medium violet red", + "midnightblue": "Midnight blue", + "mintcream": "Mint cream", + "mistyrose": "Misty rose", + "moccasin": "Moccasin", + "navajowhite": "Navajo white", + "navy": "Navy", + "navyblue": "Navy blue", + "oldlace": "Old lace", + "olive": "Olive", + "olivedrab": "Olive drab", + "orange": "Orange", + "orangered": "Orange red", + "orchid": "Orchid", + "palegoldenrod": "Pale goldenrod", + "palegreen": "Pale green", + "paleturquoise": "Pale turquoise", + "palevioletred": "Pale violet red", + "papayawhip": "Papaya whip", + "peachpuff": "Peach puff", + "peru": "Peru", + "pink": "Pink", + "plum": "Plum", + "powderblue": "Powder blue", + "purple": "Purple", + "red": "Red", + "rosybrown": "Rosy brown", + "royalblue": "Royal blue", + "saddlebrown": "Saddle brown", + "salmon": "Salmon", + "sandybrown": "Sandy brown", + "seagreen": "Sea green", + "seashell": "Seashell", + "sienna": "Sienna", + "silver": "Silver", + "skyblue": "Sky blue", + "slateblue": "Slate blue", + "slategray": "Slate gray", + "slategrey": "Slate grey", + "snow": "Snow", + "springgreen": "Spring green", + "steelblue": "Steel blue", + "tan": "Tan", + "teal": "Teal", + "thistle": "Thistle", + "tomato": "Tomato", + "turquoise": "Turquoise", + "violet": "Violet", + "wheat": "Wheat", + "white": "White", + "whitesmoke": "White smoke", + "yellow": "Yellow", + "yellowgreen": "Yellow green" + } + } + }, + "services": { + "turn_on": { + "name": "Turn on", + "description": "Turn on one or more lights and adjust properties of the light, even when they are turned on already.", + "fields": { + "transition": { + "name": "Transition", + "description": "Duration it takes to get to next state." + }, + "rgb_color": { + "name": "Color", + "description": "The color in RGB format. A list of three integers between 0 and 255 representing the values of red, green, and blue." + }, + "rgbw_color": { + "name": "RGBW-color", + "description": "The color in RGBW format. A list of four integers between 0 and 255 representing the values of red, green, blue, and white." + }, + "rgbww_color": { + "name": "RGBWW-color", + "description": "The color in RGBWW format. A list of five integers between 0 and 255 representing the values of red, green, blue, cold white, and warm white." + }, + "color_name": { + "name": "Color name", + "description": "A human readable color name." + }, + "hs_color": { + "name": "Hue/Sat color", + "description": "Color in hue/sat format. A list of two integers. Hue is 0-360 and Sat is 0-100." + }, + "xy_color": { + "name": "XY-color", + "description": "Color in XY-format. A list of two decimal numbers between 0 and 1." + }, + "color_temp": { + "name": "Color temperature", + "description": "Color temperature in mireds." + }, + "kelvin": { + "name": "Color temperature", + "description": "Color temperature in Kelvin." + }, + "brightness": { + "name": "Brightness value", + "description": "Number indicating brightness, where 0 turns the light off, 1 is the minimum brightness, and 255 is the maximum brightness." + }, + "brightness_pct": { + "name": "Brightness", + "description": "Number indicating the percentage of full brightness, where 0 turns the light off, 1 is the minimum brightness, and 100 is the maximum brightness." + }, + "brightness_step": { + "name": "Brightness step value", + "description": "Change brightness by an amount." + }, + "brightness_step_pct": { + "name": "Brightness step", + "description": "Change brightness by a percentage." + }, + "white": { + "name": "White", + "description": "Set the light to white mode." + }, + "profile": { + "name": "Profile", + "description": "Name of a light profile to use." + }, + "flash": { + "name": "Flash", + "description": "If the light should flash." + }, + "effect": { + "name": "Effect", + "description": "Light effect." + } + } + }, + "turn_off": { + "name": "Turn off", + "description": "Turn off one or more lights.", + "fields": { + "transition": { + "name": "[%key:component::light::services::turn_on::fields::transition::name%]", + "description": "[%key:component::light::services::turn_on::fields::transition::description%]" + }, + "flash": { + "name": "[%key:component::light::services::turn_on::fields::flash::name%]", + "description": "[%key:component::light::services::turn_on::fields::flash::description%]" + } + } + }, + "toggle": { + "name": "Toggle", + "description": "Toggles one or more lights, from on to off, or, off to on, based on their current state.", + "fields": { + "transition": { + "name": "[%key:component::light::services::turn_on::fields::transition::name%]", + "description": "[%key:component::light::services::turn_on::fields::transition::description%]" + }, + "rgb_color": { + "name": "[%key:component::light::services::turn_on::fields::rgb_color::name%]", + "description": "[%key:component::light::services::turn_on::fields::rgb_color::description%]" + }, + "color_name": { + "name": "[%key:component::light::services::turn_on::fields::color_name::name%]", + "description": "[%key:component::light::services::turn_on::fields::color_name::description%]" + }, + "hs_color": { + "name": "[%key:component::light::services::turn_on::fields::hs_color::name%]", + "description": "[%key:component::light::services::turn_on::fields::hs_color::description%]" + }, + "xy_color": { + "name": "[%key:component::light::services::turn_on::fields::xy_color::name%]", + "description": "[%key:component::light::services::turn_on::fields::xy_color::description%]" + }, + "color_temp": { + "name": "[%key:component::light::services::turn_on::fields::color_temp::name%]", + "description": "[%key:component::light::services::turn_on::fields::color_temp::description%]" + }, + "kelvin": { + "name": "[%key:component::light::services::turn_on::fields::kelvin::name%]", + "description": "[%key:component::light::services::turn_on::fields::kelvin::description%]" + }, + "brightness": { + "name": "[%key:component::light::services::turn_on::fields::brightness::name%]", + "description": "[%key:component::light::services::turn_on::fields::brightness::description%]" + }, + "brightness_pct": { + "name": "[%key:component::light::services::turn_on::fields::brightness_pct::name%]", + "description": "[%key:component::light::services::turn_on::fields::brightness_pct::description%]" + }, + "white": { + "name": "[%key:component::light::services::turn_on::fields::white::name%]", + "description": "[%key:component::light::services::turn_on::fields::white::description%]" + }, + "profile": { + "name": "[%key:component::light::services::turn_on::fields::profile::name%]", + "description": "[%key:component::light::services::turn_on::fields::profile::description%]" + }, + "flash": { + "name": "[%key:component::light::services::turn_on::fields::flash::name%]", + "description": "[%key:component::light::services::turn_on::fields::flash::description%]" + }, + "effect": { + "name": "[%key:component::light::services::turn_on::fields::effect::name%]", + "description": "[%key:component::light::services::turn_on::fields::effect::description%]" + } + } + } } } diff --git a/homeassistant/helpers/service.py b/homeassistant/helpers/service.py index 40bb96506309e8..1a418a68fd1c9d 100644 --- a/homeassistant/helpers/service.py +++ b/homeassistant/helpers/service.py @@ -50,6 +50,7 @@ device_registry, entity_registry, template, + translation, ) from .selector import TargetSelector from .typing import ConfigType, TemplateVarsType @@ -607,6 +608,11 @@ async def async_get_all_descriptions( ) loaded = dict(zip(missing, contents)) + # Load translations for all service domains + translations = await translation.async_get_translations( + hass, "en", "services", list(services) + ) + # Build response descriptions: dict[str, dict[str, Any]] = {} for domain, services_map in services.items(): @@ -616,37 +622,62 @@ async def async_get_all_descriptions( for service_name in services_map: cache_key = (domain, service_name) description = descriptions_cache.get(cache_key) + if description is not None: + domain_descriptions[service_name] = description + continue + # Cache missing descriptions - if description is None: - domain_yaml = loaded.get(domain) or {} - # The YAML may be empty for dynamically defined - # services (ie shell_command) that never call - # service.async_set_service_schema for the dynamic - # service - - yaml_description = domain_yaml.get( # type: ignore[union-attr] - service_name, {} - ) + domain_yaml = loaded.get(domain) or {} + # The YAML may be empty for dynamically defined + # services (ie shell_command) that never call + # service.async_set_service_schema for the dynamic + # service + + yaml_description = domain_yaml.get( # type: ignore[union-attr] + service_name, {} + ) - # Don't warn for missing services, because it triggers false - # positives for things like scripts, that register as a service - description = { - "name": yaml_description.get("name", ""), - "description": yaml_description.get("description", ""), - "fields": yaml_description.get("fields", {}), + # Don't warn for missing services, because it triggers false + # positives for things like scripts, that register as a service + # + # When name & description are in the translations use those; + # otherwise fallback to backwards compatible behavior from + # the time when we didn't have translations for descriptions yet. + # This mimics the behavior of the frontend. + description = { + "name": translations.get( + f"component.{domain}.services.{service_name}.name", + yaml_description.get("name", ""), + ), + "description": translations.get( + f"component.{domain}.services.{service_name}.description", + yaml_description.get("description", ""), + ), + "fields": dict(yaml_description.get("fields", {})), + } + + # Translate fields names & descriptions as well + for field_name, field_schema in description["fields"].items(): + if name := translations.get( + f"component.{domain}.services.{service_name}.fields.{field_name}.name" + ): + field_schema["name"] = name + if desc := translations.get( + f"component.{domain}.services.{service_name}.fields.{field_name}.description" + ): + field_schema["description"] = desc + + if "target" in yaml_description: + description["target"] = yaml_description["target"] + + if ( + response := hass.services.supports_response(domain, service_name) + ) != SupportsResponse.NONE: + description["response"] = { + "optional": response == SupportsResponse.OPTIONAL, } - if "target" in yaml_description: - description["target"] = yaml_description["target"] - - if ( - response := hass.services.supports_response(domain, service_name) - ) != SupportsResponse.NONE: - description["response"] = { - "optional": response == SupportsResponse.OPTIONAL, - } - - descriptions_cache[cache_key] = description + descriptions_cache[cache_key] = description domain_descriptions[service_name] = description diff --git a/homeassistant/helpers/translation.py b/homeassistant/helpers/translation.py index 96ce9b618c2d9a..79ac3a0c5b73b2 100644 --- a/homeassistant/helpers/translation.py +++ b/homeassistant/helpers/translation.py @@ -302,7 +302,7 @@ async def async_get_translations( components = set(integrations) elif config_flow: components = (await async_get_config_flows(hass)) - hass.config.components - elif category in ("state", "entity_component"): + elif category in ("state", "entity_component", "services"): components = set(hass.config.components) else: # Only 'state' supports merging, so remove platforms from selection diff --git a/script/hassfest/services.py b/script/hassfest/services.py index a0c629567fac9f..e0e771ee11d606 100644 --- a/script/hassfest/services.py +++ b/script/hassfest/services.py @@ -1,6 +1,8 @@ """Validate dependencies.""" from __future__ import annotations +import contextlib +import json import pathlib import re from typing import Any @@ -25,7 +27,7 @@ def exists(value: Any) -> Any: FIELD_SCHEMA = vol.Schema( { - vol.Required("description"): str, + vol.Optional("description"): str, vol.Optional("name"): str, vol.Optional("example"): exists, vol.Optional("default"): exists, @@ -46,7 +48,7 @@ def exists(value: Any) -> Any: SERVICE_SCHEMA = vol.Schema( { - vol.Required("description"): str, + vol.Optional("description"): str, vol.Optional("name"): str, vol.Optional("target"): vol.Any(selector.TargetSelector.CONFIG_SCHEMA, None), vol.Optional("fields"): vol.Schema({str: FIELD_SCHEMA}), @@ -70,7 +72,7 @@ def grep_dir(path: pathlib.Path, glob_pattern: str, search_pattern: str) -> bool return False -def validate_services(integration: Integration) -> None: +def validate_services(config: Config, integration: Integration) -> None: """Validate services.""" try: data = load_yaml(str(integration.path / "services.yaml")) @@ -92,15 +94,75 @@ def validate_services(integration: Integration) -> None: return try: - SERVICES_SCHEMA(data) + services = SERVICES_SCHEMA(data) except vol.Invalid as err: integration.add_error( "services", f"Invalid services.yaml: {humanize_error(data, err)}" ) + # Try loading translation strings + if integration.core: + strings_file = integration.path / "strings.json" + else: + # For custom integrations, use the en.json file + strings_file = integration.path / "translations/en.json" + + strings = {} + if strings_file.is_file(): + with contextlib.suppress(ValueError): + strings = json.loads(strings_file.read_text()) + + # For each service in the integration, check if the description if set, + # if not, check if it's in the strings file. If not, add an error. + for service_name, service_schema in services.items(): + if "name" not in service_schema: + try: + strings["services"][service_name]["name"] + except KeyError: + integration.add_error( + "services", + f"Service {service_name} has no name and is not in the translations file", + ) + + if "description" not in service_schema: + try: + strings["services"][service_name]["description"] + except KeyError: + integration.add_error( + "services", + f"Service {service_name} has no description and is not in the translations file", + ) + + # The same check is done for the description in each of the fields of the + # service schema. + for field_name, field_schema in service_schema.get("fields", {}).items(): + if "description" not in field_schema: + try: + strings["services"][service_name]["fields"][field_name][ + "description" + ] + except KeyError: + integration.add_error( + "services", + f"Service {service_name} has a field {field_name} with no description and is not in the translations file", + ) + + if "selector" in field_schema: + with contextlib.suppress(KeyError): + translation_key = field_schema["selector"]["select"][ + "translation_key" + ] + try: + strings["selector"][translation_key] + except KeyError: + integration.add_error( + "services", + f"Service {service_name} has a field {field_name} with a selector with a translation key {translation_key} that is not in the translations file", + ) + def validate(integrations: dict[str, Integration], config: Config) -> None: """Handle dependencies for integrations.""" # check services.yaml is cool for integration in integrations.values(): - validate_services(integration) + validate_services(config, integration) diff --git a/script/hassfest/translations.py b/script/hassfest/translations.py index e53b311b43e44b..597b8e1ae1f62e 100644 --- a/script/hassfest/translations.py +++ b/script/hassfest/translations.py @@ -326,6 +326,20 @@ def gen_strings_schema(config: Config, integration: Integration) -> vol.Schema: ), slug_validator=cv.slug, ), + vol.Optional("services"): cv.schema_with_slug_keys( + { + vol.Required("name"): translation_value_validator, + vol.Required("description"): translation_value_validator, + vol.Optional("fields"): cv.schema_with_slug_keys( + { + vol.Required("name"): str, + vol.Required("description"): translation_value_validator, + }, + slug_validator=translation_key_validator, + ), + }, + slug_validator=translation_key_validator, + ), } ) diff --git a/tests/helpers/test_service.py b/tests/helpers/test_service.py index bc7a93f0f19d75..a99f303f6c99f7 100644 --- a/tests/helpers/test_service.py +++ b/tests/helpers/test_service.py @@ -1,6 +1,8 @@ """Test service helpers.""" from collections import OrderedDict +from collections.abc import Iterable from copy import deepcopy +from typing import Any from unittest.mock import AsyncMock, Mock, patch import pytest @@ -556,13 +558,47 @@ async def test_async_get_all_descriptions(hass: HomeAssistant) -> None: logger = hass.components.logger logger_config = {logger.DOMAIN: {}} - await async_setup_component(hass, logger.DOMAIN, logger_config) - descriptions = await service.async_get_all_descriptions(hass) + + async def async_get_translations( + hass: HomeAssistant, + language: str, + category: str, + integrations: Iterable[str] | None = None, + config_flow: bool | None = None, + ) -> dict[str, Any]: + """Return all backend translations.""" + translation_key_prefix = f"component.{logger.DOMAIN}.services.set_default_level" + return { + f"{translation_key_prefix}.name": "Translated name", + f"{translation_key_prefix}.description": "Translated description", + f"{translation_key_prefix}.fields.level.name": "Field name", + f"{translation_key_prefix}.fields.level.description": "Field description", + } + + with patch( + "homeassistant.helpers.service.translation.async_get_translations", + side_effect=async_get_translations, + ): + await async_setup_component(hass, logger.DOMAIN, logger_config) + descriptions = await service.async_get_all_descriptions(hass) assert len(descriptions) == 2 - assert "description" in descriptions[logger.DOMAIN]["set_level"] - assert "fields" in descriptions[logger.DOMAIN]["set_level"] + assert descriptions[logger.DOMAIN]["set_default_level"]["name"] == "Translated name" + assert ( + descriptions[logger.DOMAIN]["set_default_level"]["description"] + == "Translated description" + ) + assert ( + descriptions[logger.DOMAIN]["set_default_level"]["fields"]["level"]["name"] + == "Field name" + ) + assert ( + descriptions[logger.DOMAIN]["set_default_level"]["fields"]["level"][ + "description" + ] + == "Field description" + ) hass.services.async_register(logger.DOMAIN, "new_service", lambda x: None, None) service.async_set_service_schema( @@ -602,7 +638,6 @@ async def test_async_get_all_descriptions(hass: HomeAssistant) -> None: "another_service_with_response", {"description": "response service"}, ) - descriptions = await service.async_get_all_descriptions(hass) assert "another_new_service" in descriptions[logger.DOMAIN] assert "service_with_optional_response" in descriptions[logger.DOMAIN] From 107f589a2e18b41062c376ffb75cbf7200a2a36f Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 11 Jul 2023 16:38:18 +0200 Subject: [PATCH 015/154] Remove some duplicated translations (#96300) --- homeassistant/components/automation/strings.json | 2 +- homeassistant/components/counter/strings.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/automation/strings.json b/homeassistant/components/automation/strings.json index 4e433119a2ae98..6f925fe090db89 100644 --- a/homeassistant/components/automation/strings.json +++ b/homeassistant/components/automation/strings.json @@ -38,7 +38,7 @@ "fix_flow": { "step": { "confirm": { - "title": "{name} uses an unknown service", + "title": "[%key:component::automation::issues::service_not_found::title%]", "description": "The automation \"{name}\" (`{entity_id}`) has an action that calls an unknown service: `{service}`.\n\nThis error prevents the automation from running correctly. Maybe this service is no longer available, or perhaps a typo caused it.\n\nTo fix this error, [edit the automation]({edit}) and remove the action that calls this service.\n\nClick on SUBMIT below to confirm you have fixed this automation." } } diff --git a/homeassistant/components/counter/strings.json b/homeassistant/components/counter/strings.json index 0959259465939b..6dcfe14a03a241 100644 --- a/homeassistant/components/counter/strings.json +++ b/homeassistant/components/counter/strings.json @@ -32,7 +32,7 @@ "fix_flow": { "step": { "confirm": { - "title": "The counter configure service is being removed", + "title": "[%key:component::counter::issues::deprecated_configure_service::title%]", "description": "The counter service `counter.configure` is being removed and use of it has been detected. If you want to change the current value of a counter, use the new `counter.set_value` service instead.\n\nPlease remove the use of this service from your automations and scripts and select **submit** to close this issue." } } From f2f9b20880a436e6dcc1e4022ae16cb3d70f47dc Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 16:48:07 +0200 Subject: [PATCH 016/154] Fix hassfest services check (#96337) --- script/hassfest/services.py | 1 + 1 file changed, 1 insertion(+) diff --git a/script/hassfest/services.py b/script/hassfest/services.py index e0e771ee11d606..2f8e20939db4bb 100644 --- a/script/hassfest/services.py +++ b/script/hassfest/services.py @@ -99,6 +99,7 @@ def validate_services(config: Config, integration: Integration) -> None: integration.add_error( "services", f"Invalid services.yaml: {humanize_error(data, err)}" ) + return # Try loading translation strings if integration.core: From 916e7dd35925f04237a793cf9e8eccfdf1300852 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 11 Jul 2023 17:28:54 +0200 Subject: [PATCH 017/154] Fix a couple of typos (#96298) --- homeassistant/components/device_automation/helpers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/device_automation/helpers.py b/homeassistant/components/device_automation/helpers.py index 038ded07e8aef0..83c599bc65d591 100644 --- a/homeassistant/components/device_automation/helpers.py +++ b/homeassistant/components/device_automation/helpers.py @@ -75,7 +75,7 @@ async def async_validate_device_automation_config( # config entry is loaded registry = dr.async_get(hass) if not (device := registry.async_get(validated_config[CONF_DEVICE_ID])): - # The device referenced by the device trigger does not exist + # The device referenced by the device automation does not exist raise InvalidDeviceAutomationConfig( f"Unknown device '{validated_config[CONF_DEVICE_ID]}'" ) @@ -91,7 +91,7 @@ async def async_validate_device_automation_config( break if not device_config_entry: - # The config entry referenced by the device trigger does not exist + # The config entry referenced by the device automation does not exist raise InvalidDeviceAutomationConfig( f"Device '{validated_config[CONF_DEVICE_ID]}' has no config entry from " f"domain '{validated_config[CONF_DOMAIN]}'" From 38aa62a9903651137625692328b8fed56131a9c5 Mon Sep 17 00:00:00 2001 From: Luke Date: Tue, 11 Jul 2023 11:32:06 -0400 Subject: [PATCH 018/154] Bump Roborock to v0.30.0 (#96268) bump to v0.30.0 --- homeassistant/components/roborock/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/roborock/manifest.json b/homeassistant/components/roborock/manifest.json index baab687e64a3cd..0cf6db4ae816db 100644 --- a/homeassistant/components/roborock/manifest.json +++ b/homeassistant/components/roborock/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/roborock", "iot_class": "local_polling", "loggers": ["roborock"], - "requirements": ["python-roborock==0.29.2"] + "requirements": ["python-roborock==0.30.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index e5013b24ce67a1..35aa527997c1d4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2139,7 +2139,7 @@ python-qbittorrent==0.4.3 python-ripple-api==0.0.3 # homeassistant.components.roborock -python-roborock==0.29.2 +python-roborock==0.30.0 # homeassistant.components.smarttub python-smarttub==0.0.33 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 13586bf8f262c7..4e3791da4a4ded 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1565,7 +1565,7 @@ python-picnic-api==1.1.0 python-qbittorrent==0.4.3 # homeassistant.components.roborock -python-roborock==0.29.2 +python-roborock==0.30.0 # homeassistant.components.smarttub python-smarttub==0.0.33 From 65bacdddd85455aec7ed6e283e9c45e877ca2a99 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 11 Jul 2023 17:33:49 +0200 Subject: [PATCH 019/154] Remove removed_yaml from the spotify integeration (#96261) * Add removed_yaml issue to the homeassistant integration * Remove issue translation from spotify * Remove unrelated change * Remove async_setup from spotify --- homeassistant/components/spotify/__init__.py | 20 ------------------- homeassistant/components/spotify/strings.json | 6 ------ 2 files changed, 26 deletions(-) diff --git a/homeassistant/components/spotify/__init__.py b/homeassistant/components/spotify/__init__.py index cb6484c5e3e0cd..ca9f63bbd1c302 100644 --- a/homeassistant/components/spotify/__init__.py +++ b/homeassistant/components/spotify/__init__.py @@ -13,13 +13,10 @@ from homeassistant.const import Platform from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady -from homeassistant.helpers import config_validation as cv from homeassistant.helpers.config_entry_oauth2_flow import ( OAuth2Session, async_get_config_entry_implementation, ) -from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue -from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .browse_media import async_browse_media @@ -30,7 +27,6 @@ spotify_uri_from_media_browser_url, ) -CONFIG_SCHEMA = cv.removed(DOMAIN, raise_if_present=False) PLATFORMS = [Platform.MEDIA_PLAYER] @@ -53,22 +49,6 @@ class HomeAssistantSpotifyData: session: OAuth2Session -async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: - """Set up the Spotify integration.""" - if DOMAIN in config: - async_create_issue( - hass, - DOMAIN, - "removed_yaml", - breaks_in_ha_version="2022.8.0", - is_fixable=False, - severity=IssueSeverity.WARNING, - translation_key="removed_yaml", - ) - - return True - - async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Spotify from a config entry.""" implementation = await async_get_config_entry_implementation(hass, entry) diff --git a/homeassistant/components/spotify/strings.json b/homeassistant/components/spotify/strings.json index 4405bd213102e7..caec5b8a288f58 100644 --- a/homeassistant/components/spotify/strings.json +++ b/homeassistant/components/spotify/strings.json @@ -21,11 +21,5 @@ "info": { "api_endpoint_reachable": "Spotify API endpoint reachable" } - }, - "issues": { - "removed_yaml": { - "title": "The Spotify YAML configuration has been removed", - "description": "Configuring Spotify using YAML has been removed.\n\nYour existing YAML configuration is not used by Home Assistant.\n\nRemove the YAML configuration from your configuration.yaml file and restart Home Assistant to fix this issue." - } } } From 5a87186916f86be84da2db2e49dccffffd18ad93 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Tue, 11 Jul 2023 18:01:05 +0200 Subject: [PATCH 020/154] Improve integration startup in AVM Fritz!Tools (#96269) --- homeassistant/components/fritz/common.py | 87 +++++++++++------------- tests/components/fritz/conftest.py | 11 ++- tests/components/fritz/const.py | 73 ++++++++++++++------ 3 files changed, 102 insertions(+), 69 deletions(-) diff --git a/homeassistant/components/fritz/common.py b/homeassistant/components/fritz/common.py index 26b336208fef98..81fdcde236a408 100644 --- a/homeassistant/components/fritz/common.py +++ b/homeassistant/components/fritz/common.py @@ -129,13 +129,34 @@ class Interface(TypedDict): type: str -class HostInfo(TypedDict): - """FRITZ!Box host info class.""" - - mac: str - name: str - ip: str - status: bool +HostAttributes = TypedDict( + "HostAttributes", + { + "Index": int, + "IPAddress": str, + "MACAddress": str, + "Active": bool, + "HostName": str, + "InterfaceType": str, + "X_AVM-DE_Port": int, + "X_AVM-DE_Speed": int, + "X_AVM-DE_UpdateAvailable": bool, + "X_AVM-DE_UpdateSuccessful": str, + "X_AVM-DE_InfoURL": str | None, + "X_AVM-DE_MACAddressList": str | None, + "X_AVM-DE_Model": str | None, + "X_AVM-DE_URL": str | None, + "X_AVM-DE_Guest": bool, + "X_AVM-DE_RequestClient": str, + "X_AVM-DE_VPN": bool, + "X_AVM-DE_WANAccess": str, + "X_AVM-DE_Disallow": bool, + "X_AVM-DE_IsMeshable": str, + "X_AVM-DE_Priority": str, + "X_AVM-DE_FriendlyName": str, + "X_AVM-DE_FriendlyNameIsWriteable": str, + }, +) class UpdateCoordinatorDataType(TypedDict): @@ -353,11 +374,11 @@ def signal_device_update(self) -> str: """Event specific per FRITZ!Box entry to signal updates in devices.""" return f"{DOMAIN}-device-update-{self._unique_id}" - async def _async_update_hosts_info(self) -> list[HostInfo]: + async def _async_update_hosts_info(self) -> list[HostAttributes]: """Retrieve latest hosts information from the FRITZ!Box.""" try: return await self.hass.async_add_executor_job( - self.fritz_hosts.get_hosts_info + self.fritz_hosts.get_hosts_attributes ) except Exception as ex: # pylint: disable=[broad-except] if not self.hass.is_stopping: @@ -392,29 +413,6 @@ async def async_update_call_deflections( return {int(item["DeflectionId"]): item for item in items} return {} - async def _async_get_wan_access(self, ip_address: str) -> bool | None: - """Get WAN access rule for given IP address.""" - try: - wan_access = await self.hass.async_add_executor_job( - partial( - self.connection.call_action, - "X_AVM-DE_HostFilter:1", - "GetWANAccessByIP", - NewIPv4Address=ip_address, - ) - ) - return not wan_access.get("NewDisallow") - except FRITZ_EXCEPTIONS as ex: - _LOGGER.debug( - ( - "could not get WAN access rule for client device with IP '%s'," - " error: %s" - ), - ip_address, - ex, - ) - return None - def manage_device_info( self, dev_info: Device, dev_mac: str, consider_home: bool ) -> bool: @@ -462,17 +460,17 @@ async def async_scan_devices(self, now: datetime | None = None) -> None: new_device = False hosts = {} for host in await self._async_update_hosts_info(): - if not host.get("mac"): + if not host.get("MACAddress"): continue - hosts[host["mac"]] = Device( - name=host["name"], - connected=host["status"], + hosts[host["MACAddress"]] = Device( + name=host["HostName"], + connected=host["Active"], connected_to="", connection_type="", - ip_address=host["ip"], + ip_address=host["IPAddress"], ssid=None, - wan_access=None, + wan_access="granted" in host["X_AVM-DE_WANAccess"], ) if not self.fritz_status.device_has_mesh_support or ( @@ -484,8 +482,6 @@ async def async_scan_devices(self, now: datetime | None = None) -> None: ) self.mesh_role = MeshRoles.NONE for mac, info in hosts.items(): - if info.ip_address: - info.wan_access = await self._async_get_wan_access(info.ip_address) if self.manage_device_info(info, mac, consider_home): new_device = True await self.async_send_signal_device_update(new_device) @@ -535,11 +531,6 @@ async def async_scan_devices(self, now: datetime | None = None) -> None: dev_info: Device = hosts[dev_mac] - if dev_info.ip_address: - dev_info.wan_access = await self._async_get_wan_access( - dev_info.ip_address - ) - for link in interf["node_links"]: intf = mesh_intf.get(link["node_interface_1_uid"]) if intf is not None: @@ -583,7 +574,7 @@ async def async_trigger_cleanup( ) -> None: """Trigger device trackers cleanup.""" device_hosts_list = await self.hass.async_add_executor_job( - self.fritz_hosts.get_hosts_info + self.fritz_hosts.get_hosts_attributes ) entity_reg: er.EntityRegistry = er.async_get(self.hass) @@ -600,8 +591,8 @@ async def async_trigger_cleanup( device_hosts_macs = set() device_hosts_names = set() for device in device_hosts_list: - device_hosts_macs.add(device["mac"]) - device_hosts_names.add(device["name"]) + device_hosts_macs.add(device["MACAddress"]) + device_hosts_names.add(device["HostName"]) for entry in ha_entity_reg_list: if entry.original_name is None: diff --git a/tests/components/fritz/conftest.py b/tests/components/fritz/conftest.py index 66f4cf2b879c81..acb135d01bb9ba 100644 --- a/tests/components/fritz/conftest.py +++ b/tests/components/fritz/conftest.py @@ -6,7 +6,12 @@ from fritzconnection.lib.fritzhosts import FritzHosts import pytest -from .const import MOCK_FB_SERVICES, MOCK_MESH_DATA, MOCK_MODELNAME +from .const import ( + MOCK_FB_SERVICES, + MOCK_HOST_ATTRIBUTES_DATA, + MOCK_MESH_DATA, + MOCK_MODELNAME, +) LOGGER = logging.getLogger(__name__) @@ -75,6 +80,10 @@ def get_mesh_topology(self, raw=False): """Retrurn mocked mesh data.""" return MOCK_MESH_DATA + def get_hosts_attributes(self): + """Retrurn mocked host attributes data.""" + return MOCK_HOST_ATTRIBUTES_DATA + @pytest.fixture(name="fc_data") def fc_data_mock(): diff --git a/tests/components/fritz/const.py b/tests/components/fritz/const.py index 7a89aab1af1df0..c19327fbf5e303 100644 --- a/tests/components/fritz/const.py +++ b/tests/components/fritz/const.py @@ -52,27 +52,8 @@ }, }, "Hosts1": { - "GetGenericHostEntry": [ - { - "NewIPAddress": MOCK_IPS["fritz.box"], - "NewAddressSource": "Static", - "NewLeaseTimeRemaining": 0, - "NewMACAddress": MOCK_MESH_MASTER_MAC, - "NewInterfaceType": "", - "NewActive": True, - "NewHostName": "fritz.box", - }, - { - "NewIPAddress": MOCK_IPS["printer"], - "NewAddressSource": "DHCP", - "NewLeaseTimeRemaining": 0, - "NewMACAddress": "AA:BB:CC:00:11:22", - "NewInterfaceType": "Ethernet", - "NewActive": True, - "NewHostName": "printer", - }, - ], "X_AVM-DE_GetMeshListPath": {}, + "X_AVM-DE_GetHostListPath": {}, }, "LANEthernetInterfaceConfig1": { "GetStatistics": { @@ -783,6 +764,58 @@ ], } +MOCK_HOST_ATTRIBUTES_DATA = [ + { + "Index": 1, + "IPAddress": MOCK_IPS["printer"], + "MACAddress": "AA:BB:CC:00:11:22", + "Active": True, + "HostName": "printer", + "InterfaceType": "Ethernet", + "X_AVM-DE_Port": 1, + "X_AVM-DE_Speed": 1000, + "X_AVM-DE_UpdateAvailable": False, + "X_AVM-DE_UpdateSuccessful": "unknown", + "X_AVM-DE_InfoURL": None, + "X_AVM-DE_MACAddressList": None, + "X_AVM-DE_Model": None, + "X_AVM-DE_URL": f"http://{MOCK_IPS['printer']}", + "X_AVM-DE_Guest": False, + "X_AVM-DE_RequestClient": "0", + "X_AVM-DE_VPN": False, + "X_AVM-DE_WANAccess": "granted", + "X_AVM-DE_Disallow": False, + "X_AVM-DE_IsMeshable": "0", + "X_AVM-DE_Priority": "0", + "X_AVM-DE_FriendlyName": "printer", + "X_AVM-DE_FriendlyNameIsWriteable": "1", + }, + { + "Index": 2, + "IPAddress": MOCK_IPS["fritz.box"], + "MACAddress": MOCK_MESH_MASTER_MAC, + "Active": True, + "HostName": "fritz.box", + "InterfaceType": None, + "X_AVM-DE_Port": 0, + "X_AVM-DE_Speed": 0, + "X_AVM-DE_UpdateAvailable": False, + "X_AVM-DE_UpdateSuccessful": "unknown", + "X_AVM-DE_InfoURL": None, + "X_AVM-DE_MACAddressList": f"{MOCK_MESH_MASTER_MAC},{MOCK_MESH_MASTER_WIFI1_MAC}", + "X_AVM-DE_Model": None, + "X_AVM-DE_URL": f"http://{MOCK_IPS['fritz.box']}", + "X_AVM-DE_Guest": False, + "X_AVM-DE_RequestClient": "0", + "X_AVM-DE_VPN": False, + "X_AVM-DE_WANAccess": "granted", + "X_AVM-DE_Disallow": False, + "X_AVM-DE_IsMeshable": "1", + "X_AVM-DE_Priority": "0", + "X_AVM-DE_FriendlyName": "fritz.box", + "X_AVM-DE_FriendlyNameIsWriteable": "0", + }, +] MOCK_USER_DATA = MOCK_CONFIG[DOMAIN][CONF_DEVICES][0] MOCK_DEVICE_INFO = { From c61c5a0443a3fe59b3c23b584b2cf057f7ec86d4 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 11 Jul 2023 18:20:00 +0200 Subject: [PATCH 021/154] Schedule `VacuumEntity` for removal in Home Assistant Core 2024.2 (#96236) --- homeassistant/components/vacuum/__init__.py | 45 +++++++++- homeassistant/components/vacuum/strings.json | 6 ++ tests/components/vacuum/test_init.py | 93 ++++++++++++++++++++ 3 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 tests/components/vacuum/test_init.py diff --git a/homeassistant/components/vacuum/__init__.py b/homeassistant/components/vacuum/__init__.py index 2399e5d9b3b450..8285e1d76d1e66 100644 --- a/homeassistant/components/vacuum/__init__.py +++ b/homeassistant/components/vacuum/__init__.py @@ -1,6 +1,7 @@ """Support for vacuum cleaner robots (botvacs).""" from __future__ import annotations +import asyncio from collections.abc import Mapping from dataclasses import dataclass from datetime import timedelta @@ -22,8 +23,8 @@ STATE_ON, STATE_PAUSED, ) -from homeassistant.core import HomeAssistant -import homeassistant.helpers.config_validation as cv +from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers import config_validation as cv, issue_registry as ir from homeassistant.helpers.config_validation import ( # noqa: F401 PLATFORM_SCHEMA, PLATFORM_SCHEMA_BASE, @@ -36,6 +37,7 @@ ToggleEntityDescription, ) from homeassistant.helpers.entity_component import EntityComponent +from homeassistant.helpers.entity_platform import EntityPlatform from homeassistant.helpers.icon import icon_for_battery_level from homeassistant.helpers.typing import ConfigType from homeassistant.loader import bind_hass @@ -367,6 +369,45 @@ class VacuumEntityDescription(ToggleEntityDescription): class VacuumEntity(_BaseVacuum, ToggleEntity): """Representation of a vacuum cleaner robot.""" + @callback + def add_to_platform_start( + self, + hass: HomeAssistant, + platform: EntityPlatform, + parallel_updates: asyncio.Semaphore | None, + ) -> None: + """Start adding an entity to a platform.""" + super().add_to_platform_start(hass, platform, parallel_updates) + # Don't report core integrations known to still use the deprecated base class; + # we don't worry about demo and mqtt has it's own deprecation warnings. + if self.platform.platform_name in ("demo", "mqtt"): + return + ir.async_create_issue( + hass, + DOMAIN, + f"deprecated_vacuum_base_class_{self.platform.platform_name}", + breaks_in_ha_version="2024.2.0", + is_fixable=False, + is_persistent=False, + issue_domain=self.platform.platform_name, + severity=ir.IssueSeverity.WARNING, + translation_key="deprecated_vacuum_base_class", + translation_placeholders={ + "platform": self.platform.platform_name, + }, + ) + _LOGGER.warning( + ( + "%s::%s is extending the deprecated base class VacuumEntity instead of " + "StateVacuumEntity, this is not valid and will be unsupported " + "from Home Assistant 2024.2. Please report it to the author of the '%s'" + " custom integration" + ), + self.platform.platform_name, + self.__class__.__name__, + self.platform.platform_name, + ) + entity_description: VacuumEntityDescription _attr_status: str | None = None diff --git a/homeassistant/components/vacuum/strings.json b/homeassistant/components/vacuum/strings.json index a27a60bba4f30b..93ef1e8584caf5 100644 --- a/homeassistant/components/vacuum/strings.json +++ b/homeassistant/components/vacuum/strings.json @@ -28,5 +28,11 @@ "returning": "Returning to dock" } } + }, + "issues": { + "deprecated_vacuum_base_class": { + "title": "The {platform} custom integration is using deprecated vacuum feature", + "description": "The custom integration `{platform}` is extending the deprecated base class `VacuumEntity` instead of `StateVacuumEntity`.\n\nPlease report it to the author of the `{platform}` custom integration.\n\nOnce an updated version of `{platform}` is available, install it and restart Home Assistant to fix this issue." + } } } diff --git a/tests/components/vacuum/test_init.py b/tests/components/vacuum/test_init.py new file mode 100644 index 00000000000000..eaa39bceaec3e6 --- /dev/null +++ b/tests/components/vacuum/test_init.py @@ -0,0 +1,93 @@ +"""The tests for the Vacuum entity integration.""" +from __future__ import annotations + +from collections.abc import Generator + +import pytest + +from homeassistant.components.vacuum import DOMAIN as VACUUM_DOMAIN, VacuumEntity +from homeassistant.config_entries import ConfigEntry, ConfigFlow +from homeassistant.core import HomeAssistant +from homeassistant.helpers import issue_registry as ir +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from tests.common import ( + MockConfigEntry, + MockModule, + MockPlatform, + mock_config_flow, + mock_integration, + mock_platform, +) + +TEST_DOMAIN = "test" + + +class MockFlow(ConfigFlow): + """Test flow.""" + + +@pytest.fixture(autouse=True) +def config_flow_fixture(hass: HomeAssistant) -> Generator[None, None, None]: + """Mock config flow.""" + mock_platform(hass, f"{TEST_DOMAIN}.config_flow") + + with mock_config_flow(TEST_DOMAIN, MockFlow): + yield + + +async def test_deprecated_base_class( + hass: HomeAssistant, caplog: pytest.LogCaptureFixture +) -> None: + """Test warnings when adding VacuumEntity to the state machine.""" + + async def async_setup_entry_init( + hass: HomeAssistant, config_entry: ConfigEntry + ) -> bool: + """Set up test config entry.""" + await hass.config_entries.async_forward_entry_setup(config_entry, VACUUM_DOMAIN) + return True + + mock_platform(hass, f"{TEST_DOMAIN}.config_flow") + mock_integration( + hass, + MockModule( + TEST_DOMAIN, + async_setup_entry=async_setup_entry_init, + ), + ) + + entity1 = VacuumEntity() + entity1.entity_id = "vacuum.test1" + + async def async_setup_entry_platform( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, + ) -> None: + """Set up test stt platform via config entry.""" + async_add_entities([entity1]) + + mock_platform( + hass, + f"{TEST_DOMAIN}.{VACUUM_DOMAIN}", + MockPlatform(async_setup_entry=async_setup_entry_platform), + ) + + config_entry = MockConfigEntry(domain=TEST_DOMAIN) + config_entry.add_to_hass(hass) + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + assert hass.states.get(entity1.entity_id) + + assert ( + "test::VacuumEntity is extending the deprecated base class VacuumEntity" + in caplog.text + ) + + issue_registry = ir.async_get(hass) + issue = issue_registry.async_get_issue( + VACUUM_DOMAIN, f"deprecated_vacuum_base_class_{TEST_DOMAIN}" + ) + assert issue.issue_domain == TEST_DOMAIN From a226b90943c736a9521a2cc142878c5a0aa7c03b Mon Sep 17 00:00:00 2001 From: Aaron Bach Date: Tue, 11 Jul 2023 10:21:05 -0600 Subject: [PATCH 022/154] Fix extra verbiage in Ridwell rotating category sensor (#96345) --- homeassistant/components/ridwell/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/ridwell/manifest.json b/homeassistant/components/ridwell/manifest.json index 5b9b443b65ee4d..72a29182169a10 100644 --- a/homeassistant/components/ridwell/manifest.json +++ b/homeassistant/components/ridwell/manifest.json @@ -7,5 +7,5 @@ "integration_type": "service", "iot_class": "cloud_polling", "loggers": ["aioridwell"], - "requirements": ["aioridwell==2023.01.0"] + "requirements": ["aioridwell==2023.07.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index 35aa527997c1d4..9b66ea6dbe55d8 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -327,7 +327,7 @@ aioqsw==0.3.2 aiorecollect==1.0.8 # homeassistant.components.ridwell -aioridwell==2023.01.0 +aioridwell==2023.07.0 # homeassistant.components.ruuvi_gateway aioruuvigateway==0.1.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 4e3791da4a4ded..6eca0fd720d8c4 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -302,7 +302,7 @@ aioqsw==0.3.2 aiorecollect==1.0.8 # homeassistant.components.ridwell -aioridwell==2023.01.0 +aioridwell==2023.07.0 # homeassistant.components.ruuvi_gateway aioruuvigateway==0.1.0 From 49b6c8ed6eab526feea6d86882eb4699f94402cb Mon Sep 17 00:00:00 2001 From: G Johansson Date: Tue, 11 Jul 2023 18:24:40 +0200 Subject: [PATCH 023/154] Fix diagnostics Sensibo (#96336) --- .../sensibo/snapshots/test_diagnostics.ambr | 27 +++++-------------- tests/components/sensibo/test_diagnostics.py | 1 - 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/tests/components/sensibo/snapshots/test_diagnostics.ambr b/tests/components/sensibo/snapshots/test_diagnostics.ambr index a3ec6952c6c673..b1cda16fb4dae5 100644 --- a/tests/components/sensibo/snapshots/test_diagnostics.ambr +++ b/tests/components/sensibo/snapshots/test_diagnostics.ambr @@ -1,20 +1,5 @@ # serializer version: 1 # name: test_diagnostics - dict({ - 'fanLevel': 'high', - 'horizontalSwing': 'stopped', - 'light': 'on', - 'mode': 'heat', - 'on': True, - 'swing': 'stopped', - 'targetTemperature': 25, - 'timestamp': dict({ - 'secondsAgo': -1, - 'time': '2022-04-30T11:23:30.019722Z', - }), - }) -# --- -# name: test_diagnostics.1 dict({ 'modes': dict({ 'auto': dict({ @@ -206,28 +191,28 @@ }), }) # --- -# name: test_diagnostics.2 +# name: test_diagnostics.1 dict({ 'low': 'low', 'medium': 'medium', 'quiet': 'quiet', }) # --- -# name: test_diagnostics.3 +# name: test_diagnostics.2 dict({ 'fixedmiddletop': 'fixedMiddleTop', 'fixedtop': 'fixedTop', 'stopped': 'stopped', }) # --- -# name: test_diagnostics.4 +# name: test_diagnostics.3 dict({ 'fixedcenterleft': 'fixedCenterLeft', 'fixedleft': 'fixedLeft', 'stopped': 'stopped', }) # --- -# name: test_diagnostics.5 +# name: test_diagnostics.4 dict({ 'fanlevel': 'low', 'horizontalswing': 'stopped', @@ -239,7 +224,7 @@ 'temperatureunit': 'c', }) # --- -# name: test_diagnostics.6 +# name: test_diagnostics.5 dict({ 'fanlevel': 'high', 'horizontalswing': 'stopped', @@ -251,7 +236,7 @@ 'temperatureunit': 'c', }) # --- -# name: test_diagnostics.7 +# name: test_diagnostics.6 dict({ }) # --- diff --git a/tests/components/sensibo/test_diagnostics.py b/tests/components/sensibo/test_diagnostics.py index c3e1625d623650..bc35b7fdd57852 100644 --- a/tests/components/sensibo/test_diagnostics.py +++ b/tests/components/sensibo/test_diagnostics.py @@ -21,7 +21,6 @@ async def test_diagnostics( diag = await get_diagnostics_for_config_entry(hass, hass_client, entry) - assert diag["ABC999111"]["ac_states"] == snapshot assert diag["ABC999111"]["full_capabilities"] == snapshot assert diag["ABC999111"]["fan_modes_translated"] == snapshot assert diag["ABC999111"]["swing_modes_translated"] == snapshot From 50442c56884889d42cb13c4f07220804e2c23e4f Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Tue, 11 Jul 2023 18:31:32 +0200 Subject: [PATCH 024/154] Speedup tests command_line integration (#96349) --- .../command_line/test_binary_sensor.py | 29 +++++++++------- tests/components/command_line/test_cover.py | 32 ++++++++++++----- tests/components/command_line/test_sensor.py | 29 +++++++++------- tests/components/command_line/test_switch.py | 34 +++++++++++++------ 4 files changed, 81 insertions(+), 43 deletions(-) diff --git a/tests/components/command_line/test_binary_sensor.py b/tests/components/command_line/test_binary_sensor.py index 910288d6920cae..50971219f48833 100644 --- a/tests/components/command_line/test_binary_sensor.py +++ b/tests/components/command_line/test_binary_sensor.py @@ -206,16 +206,19 @@ async def test_updating_to_often( hass: HomeAssistant, caplog: pytest.LogCaptureFixture ) -> None: """Test handling updating when command already running.""" + + wait_till_event = asyncio.Event() + wait_till_event.set() called = [] class MockCommandBinarySensor(CommandBinarySensor): - """Mock entity that updates slow.""" + """Mock entity that updates.""" async def _async_update(self) -> None: - """Update slow.""" + """Update the entity.""" called.append(1) - # Add waiting time - await asyncio.sleep(1) + # Wait till event is set + await wait_till_event.wait() with patch( "homeassistant.components.command_line.binary_sensor.CommandBinarySensor", @@ -232,7 +235,7 @@ async def _async_update(self) -> None: "command": "echo 1", "payload_on": "1", "payload_off": "0", - "scan_interval": 0.1, + "scan_interval": 10, } } ] @@ -241,24 +244,26 @@ async def _async_update(self) -> None: await hass.async_block_till_done() assert called + async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=15)) + wait_till_event.set() + asyncio.wait(0) assert ( "Updating Command Line Binary Sensor Test took longer than the scheduled update interval" not in caplog.text ) - called.clear() - caplog.clear() - async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=1)) - await hass.async_block_till_done() + # Simulate update takes too long + wait_till_event.clear() + async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=10)) + await asyncio.sleep(0) + async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=10)) + wait_till_event.set() - assert called assert ( "Updating Command Line Binary Sensor Test took longer than the scheduled update interval" in caplog.text ) - await asyncio.sleep(0.2) - async def test_updating_manually( hass: HomeAssistant, caplog: pytest.LogCaptureFixture diff --git a/tests/components/command_line/test_cover.py b/tests/components/command_line/test_cover.py index d4114f9bbbd787..64fa2a60719453 100644 --- a/tests/components/command_line/test_cover.py +++ b/tests/components/command_line/test_cover.py @@ -293,16 +293,19 @@ async def test_updating_to_often( hass: HomeAssistant, caplog: pytest.LogCaptureFixture ) -> None: """Test handling updating when command already running.""" + called = [] + wait_till_event = asyncio.Event() + wait_till_event.set() class MockCommandCover(CommandCover): - """Mock entity that updates slow.""" + """Mock entity that updates.""" async def _async_update(self) -> None: - """Update slow.""" + """Update the entity.""" called.append(1) # Add waiting time - await asyncio.sleep(1) + await wait_till_event.wait() with patch( "homeassistant.components.command_line.cover.CommandCover", @@ -318,7 +321,7 @@ async def _async_update(self) -> None: "command_state": "echo 1", "value_template": "{{ value }}", "name": "Test", - "scan_interval": 0.1, + "scan_interval": 10, } } ] @@ -331,20 +334,31 @@ async def _async_update(self) -> None: "Updating Command Line Cover Test took longer than the scheduled update interval" not in caplog.text ) + async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=11)) + await hass.async_block_till_done() + assert called called.clear() - caplog.clear() - async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=1)) - await hass.async_block_till_done() + assert ( + "Updating Command Line Cover Test took longer than the scheduled update interval" + not in caplog.text + ) + # Simulate update takes too long + wait_till_event.clear() + async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=10)) + await asyncio.sleep(0) + async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=10)) + wait_till_event.set() + + # Finish processing update + await hass.async_block_till_done() assert called assert ( "Updating Command Line Cover Test took longer than the scheduled update interval" in caplog.text ) - await asyncio.sleep(0.2) - async def test_updating_manually( hass: HomeAssistant, caplog: pytest.LogCaptureFixture diff --git a/tests/components/command_line/test_sensor.py b/tests/components/command_line/test_sensor.py index af7bf3222a14bd..a0f8f2cdf84935 100644 --- a/tests/components/command_line/test_sensor.py +++ b/tests/components/command_line/test_sensor.py @@ -543,16 +543,18 @@ async def test_updating_to_often( hass: HomeAssistant, caplog: pytest.LogCaptureFixture ) -> None: """Test handling updating when command already running.""" + wait_till_event = asyncio.Event() + wait_till_event.set() called = [] class MockCommandSensor(CommandSensor): - """Mock entity that updates slow.""" + """Mock entity that updates.""" async def _async_update(self) -> None: - """Update slow.""" + """Update entity.""" called.append(1) - # Add waiting time - await asyncio.sleep(1) + # Wait till event is set + await wait_till_event.wait() with patch( "homeassistant.components.command_line.sensor.CommandSensor", @@ -567,7 +569,7 @@ async def _async_update(self) -> None: "sensor": { "name": "Test", "command": "echo 1", - "scan_interval": 0.1, + "scan_interval": 10, } } ] @@ -576,24 +578,27 @@ async def _async_update(self) -> None: await hass.async_block_till_done() assert called + async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=15)) + wait_till_event.set() + asyncio.wait(0) + assert ( "Updating Command Line Sensor Test took longer than the scheduled update interval" not in caplog.text ) - called.clear() - caplog.clear() - async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=1)) - await hass.async_block_till_done() + # Simulate update takes too long + wait_till_event.clear() + async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=10)) + await asyncio.sleep(0) + async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=10)) + wait_till_event.set() - assert called assert ( "Updating Command Line Sensor Test took longer than the scheduled update interval" in caplog.text ) - await asyncio.sleep(0.2) - async def test_updating_manually( hass: HomeAssistant, caplog: pytest.LogCaptureFixture diff --git a/tests/components/command_line/test_switch.py b/tests/components/command_line/test_switch.py index 12a037f0dd115e..09e8c47d708032 100644 --- a/tests/components/command_line/test_switch.py +++ b/tests/components/command_line/test_switch.py @@ -650,16 +650,19 @@ async def test_updating_to_often( hass: HomeAssistant, caplog: pytest.LogCaptureFixture ) -> None: """Test handling updating when command already running.""" + called = [] + wait_till_event = asyncio.Event() + wait_till_event.set() class MockCommandSwitch(CommandSwitch): - """Mock entity that updates slow.""" + """Mock entity that updates.""" async def _async_update(self) -> None: - """Update slow.""" + """Update entity.""" called.append(1) - # Add waiting time - await asyncio.sleep(1) + # Wait till event is set + await wait_till_event.wait() with patch( "homeassistant.components.command_line.switch.CommandSwitch", @@ -676,7 +679,7 @@ async def _async_update(self) -> None: "command_on": "echo 2", "command_off": "echo 3", "name": "Test", - "scan_interval": 0.1, + "scan_interval": 10, } } ] @@ -689,20 +692,31 @@ async def _async_update(self) -> None: "Updating Command Line Switch Test took longer than the scheduled update interval" not in caplog.text ) + async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=11)) + await hass.async_block_till_done() + assert called called.clear() - caplog.clear() - async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=1)) - await hass.async_block_till_done() + assert ( + "Updating Command Line Switch Test took longer than the scheduled update interval" + not in caplog.text + ) + + # Simulate update takes too long + wait_till_event.clear() + async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=10)) + await asyncio.sleep(0) + async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=10)) + wait_till_event.set() + # Finish processing update + await hass.async_block_till_done() assert called assert ( "Updating Command Line Switch Test took longer than the scheduled update interval" in caplog.text ) - await asyncio.sleep(0.2) - async def test_updating_manually( hass: HomeAssistant, caplog: pytest.LogCaptureFixture From f25d5a157a9d38e605da290ac45d88bdf1275a8d Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 19:33:07 +0200 Subject: [PATCH 025/154] Fix service schema to allow for services without any fields/properties (#96346) --- homeassistant/helpers/service.py | 4 ++-- script/hassfest/services.py | 21 ++++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/homeassistant/helpers/service.py b/homeassistant/helpers/service.py index 1a418a68fd1c9d..946340ea69cae7 100644 --- a/homeassistant/helpers/service.py +++ b/homeassistant/helpers/service.py @@ -633,8 +633,8 @@ async def async_get_all_descriptions( # service.async_set_service_schema for the dynamic # service - yaml_description = domain_yaml.get( # type: ignore[union-attr] - service_name, {} + yaml_description = ( + domain_yaml.get(service_name) or {} # type: ignore[union-attr] ) # Don't warn for missing services, because it triggers false diff --git a/script/hassfest/services.py b/script/hassfest/services.py index 2f8e20939db4bb..b3f59ab66a3813 100644 --- a/script/hassfest/services.py +++ b/script/hassfest/services.py @@ -46,13 +46,18 @@ def exists(value: Any) -> Any: } ) -SERVICE_SCHEMA = vol.Schema( - { - vol.Optional("description"): str, - vol.Optional("name"): str, - vol.Optional("target"): vol.Any(selector.TargetSelector.CONFIG_SCHEMA, None), - vol.Optional("fields"): vol.Schema({str: FIELD_SCHEMA}), - } +SERVICE_SCHEMA = vol.Any( + vol.Schema( + { + vol.Optional("description"): str, + vol.Optional("name"): str, + vol.Optional("target"): vol.Any( + selector.TargetSelector.CONFIG_SCHEMA, None + ), + vol.Optional("fields"): vol.Schema({str: FIELD_SCHEMA}), + } + ), + None, ) SERVICES_SCHEMA = vol.Schema({cv.slug: SERVICE_SCHEMA}) @@ -116,6 +121,8 @@ def validate_services(config: Config, integration: Integration) -> None: # For each service in the integration, check if the description if set, # if not, check if it's in the strings file. If not, add an error. for service_name, service_schema in services.items(): + if service_schema is None: + continue if "name" not in service_schema: try: strings["services"][service_name]["name"] From 2f6826dbe36cab4da93c613006abe2f4f70452e7 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Tue, 11 Jul 2023 19:40:15 +0200 Subject: [PATCH 026/154] Use DeviceInfo object s-x (#96281) * Use DeviceInfo object o-x * Use DeviceInfo object --- .../components/sfr_box/binary_sensor.py | 5 ++++- homeassistant/components/sfr_box/button.py | 5 ++++- homeassistant/components/sfr_box/sensor.py | 5 ++++- homeassistant/components/shelly/climate.py | 4 +++- .../components/traccar/device_tracker.py | 8 ++++++-- homeassistant/components/venstar/__init__.py | 17 +++++++++-------- homeassistant/components/vulcan/calendar.py | 18 +++++++++--------- homeassistant/components/xiaomi_miio/sensor.py | 5 ++++- 8 files changed, 43 insertions(+), 24 deletions(-) diff --git a/homeassistant/components/sfr_box/binary_sensor.py b/homeassistant/components/sfr_box/binary_sensor.py index e4d41fb0cb853e..9e8201bc1b58c8 100644 --- a/homeassistant/components/sfr_box/binary_sensor.py +++ b/homeassistant/components/sfr_box/binary_sensor.py @@ -15,6 +15,7 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity @@ -112,7 +113,9 @@ def __init__( self._attr_unique_id = ( f"{system_info.mac_addr}_{coordinator.name}_{description.key}" ) - self._attr_device_info = {"identifiers": {(DOMAIN, system_info.mac_addr)}} + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, system_info.mac_addr)}, + ) @property def is_on(self) -> bool | None: diff --git a/homeassistant/components/sfr_box/button.py b/homeassistant/components/sfr_box/button.py index f6741da1398413..ab987944acc116 100644 --- a/homeassistant/components/sfr_box/button.py +++ b/homeassistant/components/sfr_box/button.py @@ -19,6 +19,7 @@ from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import DOMAIN @@ -100,7 +101,9 @@ def __init__( self.entity_description = description self._box = box self._attr_unique_id = f"{system_info.mac_addr}_{description.key}" - self._attr_device_info = {"identifiers": {(DOMAIN, system_info.mac_addr)}} + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, system_info.mac_addr)}, + ) @with_error_wrapping async def async_press(self) -> None: diff --git a/homeassistant/components/sfr_box/sensor.py b/homeassistant/components/sfr_box/sensor.py index 19512f4382157d..fa754bbe62f1dd 100644 --- a/homeassistant/components/sfr_box/sensor.py +++ b/homeassistant/components/sfr_box/sensor.py @@ -20,6 +20,7 @@ UnitOfTemperature, ) from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType from homeassistant.helpers.update_coordinator import CoordinatorEntity @@ -252,7 +253,9 @@ def __init__( self._attr_unique_id = ( f"{system_info.mac_addr}_{coordinator.name}_{description.key}" ) - self._attr_device_info = {"identifiers": {(DOMAIN, system_info.mac_addr)}} + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, system_info.mac_addr)}, + ) @property def native_value(self) -> StateType: diff --git a/homeassistant/components/shelly/climate.py b/homeassistant/components/shelly/climate.py index 6cd4c19c638d90..4cc5cacbde39a0 100644 --- a/homeassistant/components/shelly/climate.py +++ b/homeassistant/components/shelly/climate.py @@ -254,7 +254,9 @@ def preset_modes(self) -> list[str]: @property def device_info(self) -> DeviceInfo: """Device info.""" - return {"connections": {(CONNECTION_NETWORK_MAC, self.coordinator.mac)}} + return DeviceInfo( + connections={(CONNECTION_NETWORK_MAC, self.coordinator.mac)}, + ) def _check_is_off(self) -> bool: """Return if valve is off or on.""" diff --git a/homeassistant/components/traccar/device_tracker.py b/homeassistant/components/traccar/device_tracker.py index 9ed7922fa19f66..a22b8a993f1b9c 100644 --- a/homeassistant/components/traccar/device_tracker.py +++ b/homeassistant/components/traccar/device_tracker.py @@ -39,6 +39,7 @@ from homeassistant.helpers import config_validation as cv, device_registry as dr from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.dispatcher import async_dispatcher_connect +from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.event import async_track_time_interval from homeassistant.helpers.restore_state import RestoreEntity @@ -411,9 +412,12 @@ def unique_id(self): return self._unique_id @property - def device_info(self): + def device_info(self) -> DeviceInfo: """Return the device info.""" - return {"name": self._name, "identifiers": {(DOMAIN, self._unique_id)}} + return DeviceInfo( + name=self._name, + identifiers={(DOMAIN, self._unique_id)}, + ) @property def source_type(self) -> SourceType: diff --git a/homeassistant/components/venstar/__init__.py b/homeassistant/components/venstar/__init__.py index 48760a8bfc0811..4b2d29558324c4 100644 --- a/homeassistant/components/venstar/__init__.py +++ b/homeassistant/components/venstar/__init__.py @@ -18,6 +18,7 @@ ) from homeassistant.core import HomeAssistant, callback from homeassistant.helpers import update_coordinator +from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.update_coordinator import CoordinatorEntity from .const import _LOGGER, DOMAIN, VENSTAR_SLEEP, VENSTAR_TIMEOUT @@ -143,12 +144,12 @@ def _handle_coordinator_update(self) -> None: self.async_write_ha_state() @property - def device_info(self): + def device_info(self) -> DeviceInfo: """Return the device information for this entity.""" - return { - "identifiers": {(DOMAIN, self._config.entry_id)}, - "name": self._client.name, - "manufacturer": "Venstar", - "model": f"{self._client.model}-{self._client.get_type()}", - "sw_version": self._client.get_api_ver(), - } + return DeviceInfo( + identifiers={(DOMAIN, self._config.entry_id)}, + name=self._client.name, + manufacturer="Venstar", + model=f"{self._client.model}-{self._client.get_type()}", + sw_version=self._client.get_api_ver(), + ) diff --git a/homeassistant/components/vulcan/calendar.py b/homeassistant/components/vulcan/calendar.py index d9182bb9905679..debf1f4ea0dfeb 100644 --- a/homeassistant/components/vulcan/calendar.py +++ b/homeassistant/components/vulcan/calendar.py @@ -16,7 +16,7 @@ from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed from homeassistant.helpers.device_registry import DeviceEntryType -from homeassistant.helpers.entity import generate_entity_id +from homeassistant.helpers.entity import DeviceInfo, generate_entity_id from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import DOMAIN @@ -64,19 +64,19 @@ def __init__(self, client, data, entity_id) -> None: self._unique_id = f"vulcan_calendar_{self.student_info['id']}" self._attr_name = f"Vulcan calendar - {self.student_info['full_name']}" self._attr_unique_id = f"vulcan_calendar_{self.student_info['id']}" - self._attr_device_info = { - "identifiers": {(DOMAIN, f"calendar_{self.student_info['id']}")}, - "entry_type": DeviceEntryType.SERVICE, - "name": f"{self.student_info['full_name']}: Calendar", - "model": ( + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, f"calendar_{self.student_info['id']}")}, + entry_type=DeviceEntryType.SERVICE, + name=f"{self.student_info['full_name']}: Calendar", + model=( f"{self.student_info['full_name']} -" f" {self.student_info['class']} {self.student_info['school']}" ), - "manufacturer": "Uonet +", - "configuration_url": ( + manufacturer="Uonet +", + configuration_url=( f"https://uonetplus.vulcan.net.pl/{self.student_info['symbol']}" ), - } + ) @property def event(self) -> CalendarEvent | None: diff --git a/homeassistant/components/xiaomi_miio/sensor.py b/homeassistant/components/xiaomi_miio/sensor.py index 249774519d0832..b28f06eb97d6e5 100644 --- a/homeassistant/components/xiaomi_miio/sensor.py +++ b/homeassistant/components/xiaomi_miio/sensor.py @@ -42,6 +42,7 @@ UnitOfVolume, ) from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.util import dt as dt_util @@ -997,7 +998,9 @@ def __init__(self, gateway_device, gateway_name, gateway_device_id, description) """Initialize the entity.""" self._attr_name = f"{gateway_name} {description.name}" self._attr_unique_id = f"{gateway_device_id}-{description.key}" - self._attr_device_info = {"identifiers": {(DOMAIN, gateway_device_id)}} + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, gateway_device_id)}, + ) self._gateway = gateway_device self.entity_description = description self._available = False From a04aaf10a59049ce13f27342f1e84a2c551856ab Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Tue, 11 Jul 2023 19:41:55 +0200 Subject: [PATCH 027/154] Use DeviceInfo object d-o (#96280) --- homeassistant/components/demo/button.py | 9 +++++---- homeassistant/components/demo/climate.py | 9 +++++---- homeassistant/components/elmax/common.py | 17 +++++++++-------- homeassistant/components/kmtronic/switch.py | 13 +++++++------ homeassistant/components/lcn/__init__.py | 14 +++++++------- .../components/lutron_caseta/__init__.py | 16 ++++++++-------- homeassistant/components/overkiz/entity.py | 6 +++--- homeassistant/components/overkiz/sensor.py | 6 +++--- 8 files changed, 47 insertions(+), 43 deletions(-) diff --git a/homeassistant/components/demo/button.py b/homeassistant/components/demo/button.py index f7a653e17797a2..02f3f584003a26 100644 --- a/homeassistant/components/demo/button.py +++ b/homeassistant/components/demo/button.py @@ -5,6 +5,7 @@ from homeassistant.components.button import ButtonEntity from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import DOMAIN @@ -43,10 +44,10 @@ def __init__( """Initialize the Demo button entity.""" self._attr_unique_id = unique_id self._attr_icon = icon - self._attr_device_info = { - "identifiers": {(DOMAIN, unique_id)}, - "name": device_name, - } + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, unique_id)}, + name=device_name, + ) async def async_press(self) -> None: """Send out a persistent notification.""" diff --git a/homeassistant/components/demo/climate.py b/homeassistant/components/demo/climate.py index 340a4b306cba49..407860526ae797 100644 --- a/homeassistant/components/demo/climate.py +++ b/homeassistant/components/demo/climate.py @@ -14,6 +14,7 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import ATTR_TEMPERATURE, UnitOfTemperature from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import DOMAIN @@ -152,10 +153,10 @@ def __init__( self._swing_modes = ["auto", "1", "2", "3", "off"] self._target_temperature_high = target_temp_high self._target_temperature_low = target_temp_low - self._attr_device_info = { - "identifiers": {(DOMAIN, unique_id)}, - "name": device_name, - } + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, unique_id)}, + name=device_name, + ) @property def unique_id(self) -> str: diff --git a/homeassistant/components/elmax/common.py b/homeassistant/components/elmax/common.py index 5334da23125149..b0f51740b04ef1 100644 --- a/homeassistant/components/elmax/common.py +++ b/homeassistant/components/elmax/common.py @@ -21,6 +21,7 @@ from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed, HomeAssistantError +from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.update_coordinator import ( CoordinatorEntity, DataUpdateCoordinator, @@ -168,17 +169,17 @@ def name(self) -> str | None: return self._device.name @property - def device_info(self): + def device_info(self) -> DeviceInfo: """Return device specific attributes.""" - return { - "identifiers": {(DOMAIN, self._panel.hash)}, - "name": self._panel.get_name_by_user( + return DeviceInfo( + identifiers={(DOMAIN, self._panel.hash)}, + name=self._panel.get_name_by_user( self.coordinator.http_client.get_authenticated_username() ), - "manufacturer": "Elmax", - "model": self._panel_version, - "sw_version": self._panel_version, - } + manufacturer="Elmax", + model=self._panel_version, + sw_version=self._panel_version, + ) @property def available(self) -> bool: diff --git a/homeassistant/components/kmtronic/switch.py b/homeassistant/components/kmtronic/switch.py index 860e5bf832eab2..ed54315de908f8 100644 --- a/homeassistant/components/kmtronic/switch.py +++ b/homeassistant/components/kmtronic/switch.py @@ -5,6 +5,7 @@ from homeassistant.components.switch import SwitchEntity from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity @@ -38,12 +39,12 @@ def __init__(self, hub, coordinator, relay, reverse, config_entry_id): self._reverse = reverse hostname = urllib.parse.urlsplit(hub.host).hostname - self._attr_device_info = { - "identifiers": {(DOMAIN, config_entry_id)}, - "name": f"Controller {hostname}", - "manufacturer": MANUFACTURER, - "configuration_url": hub.host, - } + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, config_entry_id)}, + name=f"Controller {hostname}", + manufacturer=MANUFACTURER, + configuration_url=hub.host, + ) self._attr_name = f"Relay{relay.id}" self._attr_unique_id = f"{config_entry_id}_relay{relay.id}" diff --git a/homeassistant/components/lcn/__init__.py b/homeassistant/components/lcn/__init__.py index 2e1185fd69215d..72b66bc5cf1929 100644 --- a/homeassistant/components/lcn/__init__.py +++ b/homeassistant/components/lcn/__init__.py @@ -276,16 +276,16 @@ def device_info(self) -> DeviceInfo | None: f" ({get_device_model(self.config[CONF_DOMAIN], self.config[CONF_DOMAIN_DATA])})" ) - return { - "identifiers": {(DOMAIN, self.unique_id)}, - "name": f"{address}.{self.config[CONF_RESOURCE]}", - "model": model, - "manufacturer": "Issendorff", - "via_device": ( + return DeviceInfo( + identifiers={(DOMAIN, self.unique_id)}, + name=f"{address}.{self.config[CONF_RESOURCE]}", + model=model, + manufacturer="Issendorff", + via_device=( DOMAIN, generate_unique_id(self.entry_id, self.config[CONF_ADDRESS]), ), - } + ) async def async_added_to_hass(self) -> None: """Run when entity about to be added to hass.""" diff --git a/homeassistant/components/lutron_caseta/__init__.py b/homeassistant/components/lutron_caseta/__init__.py index 64abf6e54c4e28..6d20f29905d243 100644 --- a/homeassistant/components/lutron_caseta/__init__.py +++ b/homeassistant/components/lutron_caseta/__init__.py @@ -219,14 +219,14 @@ def _async_register_bridge_device( """Register the bridge device in the device registry.""" device_registry = dr.async_get(hass) - device_args: DeviceInfo = { - "name": bridge_device["name"], - "manufacturer": MANUFACTURER, - "identifiers": {(DOMAIN, bridge_device["serial"])}, - "model": f"{bridge_device['model']} ({bridge_device['type']})", - "via_device": (DOMAIN, bridge_device["serial"]), - "configuration_url": "https://device-login.lutron.com", - } + device_args = DeviceInfo( + name=bridge_device["name"], + manufacturer=MANUFACTURER, + identifiers={(DOMAIN, bridge_device["serial"])}, + model=f"{bridge_device['model']} ({bridge_device['type']})", + via_device=(DOMAIN, bridge_device["serial"]), + configuration_url="https://device-login.lutron.com", + ) area = _area_name_from_id(bridge.areas, bridge_device["area"]) if area != UNASSIGNED_AREA: diff --git a/homeassistant/components/overkiz/entity.py b/homeassistant/components/overkiz/entity.py index 16ea12a5d9669d..fa531410e33d33 100644 --- a/homeassistant/components/overkiz/entity.py +++ b/homeassistant/components/overkiz/entity.py @@ -60,9 +60,9 @@ def generate_device_info(self) -> DeviceInfo: if self.is_sub_device: # Only return the url of the base device, to inherit device name # and model from parent device. - return { - "identifiers": {(DOMAIN, self.executor.base_device_url)}, - } + return DeviceInfo( + identifiers={(DOMAIN, self.executor.base_device_url)}, + ) manufacturer = ( self.executor.select_attribute(OverkizAttribute.CORE_MANUFACTURER) diff --git a/homeassistant/components/overkiz/sensor.py b/homeassistant/components/overkiz/sensor.py index 9aca0850b053eb..c841e3b0e3644a 100644 --- a/homeassistant/components/overkiz/sensor.py +++ b/homeassistant/components/overkiz/sensor.py @@ -527,6 +527,6 @@ def device_info(self) -> DeviceInfo: # By default this sensor will be listed at a virtual HomekitStack device, # but it makes more sense to show this at the gateway device # in the entity registry. - return { - "identifiers": {(DOMAIN, self.executor.get_gateway_id())}, - } + return DeviceInfo( + identifiers={(DOMAIN, self.executor.get_gateway_id())}, + ) From a0e20c6c6be79ee1f7388507f0c3a2328b004edf Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Tue, 11 Jul 2023 19:42:59 +0200 Subject: [PATCH 028/154] Bump reolink_aio to 0.7.3 (#96284) --- homeassistant/components/reolink/manifest.json | 2 +- homeassistant/components/reolink/select.py | 2 +- homeassistant/components/reolink/strings.json | 4 +++- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/reolink/manifest.json b/homeassistant/components/reolink/manifest.json index 69b3d5db6f7ed1..00f0e0f518bcfa 100644 --- a/homeassistant/components/reolink/manifest.json +++ b/homeassistant/components/reolink/manifest.json @@ -18,5 +18,5 @@ "documentation": "https://www.home-assistant.io/integrations/reolink", "iot_class": "local_push", "loggers": ["reolink_aio"], - "requirements": ["reolink-aio==0.7.1"] + "requirements": ["reolink-aio==0.7.3"] } diff --git a/homeassistant/components/reolink/select.py b/homeassistant/components/reolink/select.py index 6303bc58131926..2ae3442278e609 100644 --- a/homeassistant/components/reolink/select.py +++ b/homeassistant/components/reolink/select.py @@ -49,7 +49,7 @@ class ReolinkSelectEntityDescription( icon="mdi:spotlight-beam", entity_category=EntityCategory.CONFIG, translation_key="floodlight_mode", - get_options=[mode.name for mode in SpotlightModeEnum], + get_options=lambda api, ch: api.whiteled_mode_list(ch), supported=lambda api, ch: api.supported(ch, "floodLight"), value=lambda api, ch: SpotlightModeEnum(api.whiteled_mode(ch)).name, method=lambda api, ch, name: api.set_whiteled(ch, mode=name), diff --git a/homeassistant/components/reolink/strings.json b/homeassistant/components/reolink/strings.json index 7dc89ddbaf3f55..53f2e57b97bac5 100644 --- a/homeassistant/components/reolink/strings.json +++ b/homeassistant/components/reolink/strings.json @@ -62,7 +62,9 @@ "state": { "off": "[%key:common::state::off%]", "auto": "Auto", - "schedule": "Schedule" + "schedule": "Schedule", + "adaptive": "Adaptive", + "autoadaptive": "Auto adaptive" } }, "day_night_mode": { diff --git a/requirements_all.txt b/requirements_all.txt index 9b66ea6dbe55d8..3aaab1edf2e9a6 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2267,7 +2267,7 @@ renault-api==0.1.13 renson-endura-delta==1.5.0 # homeassistant.components.reolink -reolink-aio==0.7.1 +reolink-aio==0.7.3 # homeassistant.components.idteck_prox rfk101py==0.0.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 6eca0fd720d8c4..bddb261e3eb98d 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1660,7 +1660,7 @@ renault-api==0.1.13 renson-endura-delta==1.5.0 # homeassistant.components.reolink -reolink-aio==0.7.1 +reolink-aio==0.7.3 # homeassistant.components.rflink rflink==0.0.65 From 85ed347ff30587c851ec3000ee83489757ef10da Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 11 Jul 2023 08:08:01 -1000 Subject: [PATCH 029/154] Bump aioesphomeapi to 15.1.6 (#96297) * Bump aioesphomeapi to 15.1.5 changelog: https://github.com/esphome/aioesphomeapi/compare/v15.1.4...v15.1.5 - reduce traffic - improve error reporting * 6 --- homeassistant/components/esphome/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/esphome/manifest.json b/homeassistant/components/esphome/manifest.json index 63bd2ffc0814f4..764b12cedc2438 100644 --- a/homeassistant/components/esphome/manifest.json +++ b/homeassistant/components/esphome/manifest.json @@ -15,7 +15,7 @@ "iot_class": "local_push", "loggers": ["aioesphomeapi", "noiseprotocol"], "requirements": [ - "aioesphomeapi==15.1.4", + "aioesphomeapi==15.1.6", "bluetooth-data-tools==1.3.0", "esphome-dashboard-api==1.2.3" ], diff --git a/requirements_all.txt b/requirements_all.txt index 3aaab1edf2e9a6..17d45dcb24a9e4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -231,7 +231,7 @@ aioecowitt==2023.5.0 aioemonitor==1.0.5 # homeassistant.components.esphome -aioesphomeapi==15.1.4 +aioesphomeapi==15.1.6 # homeassistant.components.flo aioflo==2021.11.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index bddb261e3eb98d..746b5cf643e665 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -212,7 +212,7 @@ aioecowitt==2023.5.0 aioemonitor==1.0.5 # homeassistant.components.esphome -aioesphomeapi==15.1.4 +aioesphomeapi==15.1.6 # homeassistant.components.flo aioflo==2021.11.0 From 7e686db4be795b7f250ebb713040e8442e194a8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Hjelseth=20H=C3=B8yer?= Date: Tue, 11 Jul 2023 20:09:20 +0200 Subject: [PATCH 030/154] Tibber upgrade lib, improve reconnect issues (#96276) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tibber upgrade lib, improve recoonect issues Signed-off-by: Daniel Hjelseth Høyer --- homeassistant/components/tibber/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/tibber/manifest.json b/homeassistant/components/tibber/manifest.json index 1b6c5e3045ac62..c668430914fae7 100644 --- a/homeassistant/components/tibber/manifest.json +++ b/homeassistant/components/tibber/manifest.json @@ -8,5 +8,5 @@ "iot_class": "cloud_polling", "loggers": ["tibber"], "quality_scale": "silver", - "requirements": ["pyTibber==0.27.2"] + "requirements": ["pyTibber==0.28.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index 17d45dcb24a9e4..e95d879d72f3d8 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1533,7 +1533,7 @@ pyRFXtrx==0.30.1 pySDCP==1 # homeassistant.components.tibber -pyTibber==0.27.2 +pyTibber==0.28.0 # homeassistant.components.dlink pyW215==0.7.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 746b5cf643e665..e954b5a447ced6 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1148,7 +1148,7 @@ pyElectra==1.2.0 pyRFXtrx==0.30.1 # homeassistant.components.tibber -pyTibber==0.27.2 +pyTibber==0.28.0 # homeassistant.components.dlink pyW215==0.7.0 From b6e83be6f9b1d6f5ebbc71f2e7b33e16893288d8 Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Tue, 11 Jul 2023 14:09:52 -0400 Subject: [PATCH 031/154] Fix ZHA serialization issue with warning devices (#96275) * Bump ZHA dependencies * Update unit tests to reduce mocks --- homeassistant/components/zha/manifest.json | 4 +- requirements_all.txt | 4 +- requirements_test_all.txt | 4 +- tests/components/zha/test_siren.py | 88 +++++++++++++++------- 4 files changed, 68 insertions(+), 32 deletions(-) diff --git a/homeassistant/components/zha/manifest.json b/homeassistant/components/zha/manifest.json index 293822987c30ae..7694a85b8ede4f 100644 --- a/homeassistant/components/zha/manifest.json +++ b/homeassistant/components/zha/manifest.json @@ -25,10 +25,10 @@ "pyserial-asyncio==0.6", "zha-quirks==0.0.101", "zigpy-deconz==0.21.0", - "zigpy==0.56.1", + "zigpy==0.56.2", "zigpy-xbee==0.18.1", "zigpy-zigate==0.11.0", - "zigpy-znp==0.11.2" + "zigpy-znp==0.11.3" ], "usb": [ { diff --git a/requirements_all.txt b/requirements_all.txt index e95d879d72f3d8..f6d8a03cbe873f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2759,10 +2759,10 @@ zigpy-xbee==0.18.1 zigpy-zigate==0.11.0 # homeassistant.components.zha -zigpy-znp==0.11.2 +zigpy-znp==0.11.3 # homeassistant.components.zha -zigpy==0.56.1 +zigpy==0.56.2 # homeassistant.components.zoneminder zm-py==0.5.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index e954b5a447ced6..cd72a6df01b4a6 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2023,10 +2023,10 @@ zigpy-xbee==0.18.1 zigpy-zigate==0.11.0 # homeassistant.components.zha -zigpy-znp==0.11.2 +zigpy-znp==0.11.3 # homeassistant.components.zha -zigpy==0.56.1 +zigpy==0.56.2 # homeassistant.components.zwave_js zwave-js-server-python==0.49.0 diff --git a/tests/components/zha/test_siren.py b/tests/components/zha/test_siren.py index 7346f1e5bcbe27..2df6c2be5db52e 100644 --- a/tests/components/zha/test_siren.py +++ b/tests/components/zha/test_siren.py @@ -1,10 +1,11 @@ """Test zha siren.""" from datetime import timedelta -from unittest.mock import patch +from unittest.mock import ANY, call, patch import pytest from zigpy.const import SIG_EP_PROFILE import zigpy.profiles.zha as zha +import zigpy.zcl import zigpy.zcl.clusters.general as general import zigpy.zcl.clusters.security as security import zigpy.zcl.foundation as zcl_f @@ -85,48 +86,76 @@ async def test_siren(hass: HomeAssistant, siren) -> None: # turn on from HA with patch( - "zigpy.zcl.Cluster.request", + "zigpy.device.Device.request", return_value=mock_coro([0x00, zcl_f.Status.SUCCESS]), + ), patch( + "zigpy.zcl.Cluster.request", + side_effect=zigpy.zcl.Cluster.request, + autospec=True, ): # turn on via UI await hass.services.async_call( SIREN_DOMAIN, "turn_on", {"entity_id": entity_id}, blocking=True ) - assert len(cluster.request.mock_calls) == 1 - assert cluster.request.call_args[0][0] is False - assert cluster.request.call_args[0][1] == 0 - assert cluster.request.call_args[0][3] == 50 # bitmask for default args - assert cluster.request.call_args[0][4] == 5 # duration in seconds - assert cluster.request.call_args[0][5] == 0 - assert cluster.request.call_args[0][6] == 2 + assert cluster.request.mock_calls == [ + call( + cluster, + False, + 0, + ANY, + 50, # bitmask for default args + 5, # duration in seconds + 0, + 2, + manufacturer=None, + expect_reply=True, + tsn=None, + ) + ] # test that the state has changed to on assert hass.states.get(entity_id).state == STATE_ON # turn off from HA with patch( - "zigpy.zcl.Cluster.request", + "zigpy.device.Device.request", return_value=mock_coro([0x01, zcl_f.Status.SUCCESS]), + ), patch( + "zigpy.zcl.Cluster.request", + side_effect=zigpy.zcl.Cluster.request, + autospec=True, ): # turn off via UI await hass.services.async_call( SIREN_DOMAIN, "turn_off", {"entity_id": entity_id}, blocking=True ) - assert len(cluster.request.mock_calls) == 1 - assert cluster.request.call_args[0][0] is False - assert cluster.request.call_args[0][1] == 0 - assert cluster.request.call_args[0][3] == 2 # bitmask for default args - assert cluster.request.call_args[0][4] == 5 # duration in seconds - assert cluster.request.call_args[0][5] == 0 - assert cluster.request.call_args[0][6] == 2 + assert cluster.request.mock_calls == [ + call( + cluster, + False, + 0, + ANY, + 2, # bitmask for default args + 5, # duration in seconds + 0, + 2, + manufacturer=None, + expect_reply=True, + tsn=None, + ) + ] # test that the state has changed to off assert hass.states.get(entity_id).state == STATE_OFF # turn on from HA with patch( - "zigpy.zcl.Cluster.request", + "zigpy.device.Device.request", return_value=mock_coro([0x00, zcl_f.Status.SUCCESS]), + ), patch( + "zigpy.zcl.Cluster.request", + side_effect=zigpy.zcl.Cluster.request, + autospec=True, ): # turn on via UI await hass.services.async_call( @@ -140,14 +169,21 @@ async def test_siren(hass: HomeAssistant, siren) -> None: }, blocking=True, ) - assert len(cluster.request.mock_calls) == 1 - assert cluster.request.call_args[0][0] is False - assert cluster.request.call_args[0][1] == 0 - assert cluster.request.call_args[0][3] == 97 # bitmask for passed args - assert cluster.request.call_args[0][4] == 10 # duration in seconds - assert cluster.request.call_args[0][5] == 0 - assert cluster.request.call_args[0][6] == 2 - + assert cluster.request.mock_calls == [ + call( + cluster, + False, + 0, + ANY, + 97, # bitmask for passed args + 10, # duration in seconds + 0, + 2, + manufacturer=None, + expect_reply=True, + tsn=None, + ) + ] # test that the state has changed to on assert hass.states.get(entity_id).state == STATE_ON From 72f080bf8b55948f39d55c152d25c9b3556ee034 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Tue, 11 Jul 2023 20:10:14 +0200 Subject: [PATCH 032/154] Use explicit device naming for Escea (#96270) --- homeassistant/components/escea/climate.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/escea/climate.py b/homeassistant/components/escea/climate.py index df191afb859fc5..0c85705a2a6495 100644 --- a/homeassistant/components/escea/climate.py +++ b/homeassistant/components/escea/climate.py @@ -76,6 +76,7 @@ class ControllerEntity(ClimateEntity): _attr_fan_modes = list(_HA_FAN_TO_ESCEA) _attr_has_entity_name = True + _attr_name = None _attr_hvac_modes = [HVACMode.HEAT, HVACMode.OFF] _attr_icon = ICON _attr_precision = PRECISION_WHOLE From b106ca79837bbdeb8ee7d414fde0773637ae28fc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 11 Jul 2023 08:11:51 -1000 Subject: [PATCH 033/154] Fix race fetching ESPHome dashboard when there are no devices set up (#96196) * Fix fetching ESPHome dashboard when there are no devices setup fixes #96194 * coverage * fix --- .../components/esphome/config_flow.py | 6 ++- homeassistant/components/esphome/dashboard.py | 9 +++- tests/components/esphome/test_config_flow.py | 42 +++++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/esphome/config_flow.py b/homeassistant/components/esphome/config_flow.py index 9ed7ad7123d394..5011439c7780e9 100644 --- a/homeassistant/components/esphome/config_flow.py +++ b/homeassistant/components/esphome/config_flow.py @@ -35,7 +35,7 @@ DEFAULT_NEW_CONFIG_ALLOW_ALLOW_SERVICE_CALLS, DOMAIN, ) -from .dashboard import async_get_dashboard, async_set_dashboard_info +from .dashboard import async_get_or_create_dashboard_manager, async_set_dashboard_info ERROR_REQUIRES_ENCRYPTION_KEY = "requires_encryption_key" ERROR_INVALID_ENCRYPTION_KEY = "invalid_psk" @@ -406,7 +406,9 @@ async def _retrieve_encryption_key_from_dashboard(self) -> bool: """ if ( self._device_name is None - or (dashboard := async_get_dashboard(self.hass)) is None + or (manager := await async_get_or_create_dashboard_manager(self.hass)) + is None + or (dashboard := manager.async_get()) is None ): return False diff --git a/homeassistant/components/esphome/dashboard.py b/homeassistant/components/esphome/dashboard.py index 35e9cf74555968..c9d74f0b30c62a 100644 --- a/homeassistant/components/esphome/dashboard.py +++ b/homeassistant/components/esphome/dashboard.py @@ -143,7 +143,14 @@ async def on_hass_stop(_: Event) -> None: @callback def async_get_dashboard(hass: HomeAssistant) -> ESPHomeDashboard | None: - """Get an instance of the dashboard if set.""" + """Get an instance of the dashboard if set. + + This is only safe to call after `async_setup` has been completed. + + It should not be called from the config flow because there is a race + where manager can be an asyncio.Event instead of the actual manager + because the singleton decorator is not yet done. + """ manager: ESPHomeDashboardManager | None = hass.data.get(KEY_DASHBOARD_MANAGER) return manager.async_get() if manager else None diff --git a/tests/components/esphome/test_config_flow.py b/tests/components/esphome/test_config_flow.py index 28d411be9391ad..fc37e1e51ee511 100644 --- a/tests/components/esphome/test_config_flow.py +++ b/tests/components/esphome/test_config_flow.py @@ -1374,3 +1374,45 @@ async def test_option_flow( assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY assert result["data"] == {CONF_ALLOW_SERVICE_CALLS: option_value} assert len(mock_reload.mock_calls) == int(option_value) + + +async def test_user_discovers_name_no_dashboard( + hass: HomeAssistant, + mock_client, + mock_zeroconf: None, + mock_setup_entry: None, +) -> None: + """Test user step can discover the name and the there is not dashboard.""" + mock_client.device_info.side_effect = [ + RequiresEncryptionAPIError, + InvalidEncryptionKeyAPIError("Wrong key", "test"), + DeviceInfo( + uses_password=False, + name="test", + mac_address="11:22:33:44:55:AA", + ), + ] + + result = await hass.config_entries.flow.async_init( + "esphome", + context={"source": config_entries.SOURCE_USER}, + data={CONF_HOST: "127.0.0.1", CONF_PORT: 6053}, + ) + await hass.async_block_till_done() + + assert result["type"] == FlowResultType.FORM + assert result["step_id"] == "encryption_key" + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], user_input={CONF_NOISE_PSK: VALID_NOISE_PSK} + ) + + assert result["type"] == FlowResultType.CREATE_ENTRY + assert result["data"] == { + CONF_HOST: "127.0.0.1", + CONF_PORT: 6053, + CONF_PASSWORD: "", + CONF_NOISE_PSK: VALID_NOISE_PSK, + CONF_DEVICE_NAME: "test", + } + assert mock_client.noise_psk == VALID_NOISE_PSK From 7d2559e6a5ec687e3201207e719a8905a01d65ee Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Tue, 11 Jul 2023 20:12:16 +0200 Subject: [PATCH 034/154] Add has entity name to Blink (#96322) --- homeassistant/components/blink/alarm_control_panel.py | 1 + homeassistant/components/blink/binary_sensor.py | 3 ++- homeassistant/components/blink/camera.py | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/blink/alarm_control_panel.py b/homeassistant/components/blink/alarm_control_panel.py index 5d0ea67f31df76..75a2644791e03d 100644 --- a/homeassistant/components/blink/alarm_control_panel.py +++ b/homeassistant/components/blink/alarm_control_panel.py @@ -42,6 +42,7 @@ class BlinkSyncModule(AlarmControlPanelEntity): _attr_icon = ICON _attr_supported_features = AlarmControlPanelEntityFeature.ARM_AWAY _attr_name = None + _attr_has_entity_name = True def __init__(self, data, name, sync): """Initialize the alarm control panel.""" diff --git a/homeassistant/components/blink/binary_sensor.py b/homeassistant/components/blink/binary_sensor.py index c7daf0ec1e1d58..1487c6a7b42df5 100644 --- a/homeassistant/components/blink/binary_sensor.py +++ b/homeassistant/components/blink/binary_sensor.py @@ -58,13 +58,14 @@ async def async_setup_entry( class BlinkBinarySensor(BinarySensorEntity): """Representation of a Blink binary sensor.""" + _attr_has_entity_name = True + def __init__( self, data, camera, description: BinarySensorEntityDescription ) -> None: """Initialize the sensor.""" self.data = data self.entity_description = description - self._attr_name = f"{DOMAIN} {camera} {description.name}" self._camera = data.cameras[camera] self._attr_unique_id = f"{self._camera.serial}-{description.key}" self._attr_device_info = DeviceInfo( diff --git a/homeassistant/components/blink/camera.py b/homeassistant/components/blink/camera.py index e74555f8db909e..9740e427e9c823 100644 --- a/homeassistant/components/blink/camera.py +++ b/homeassistant/components/blink/camera.py @@ -38,6 +38,7 @@ async def async_setup_entry( class BlinkCamera(Camera): """An implementation of a Blink Camera.""" + _attr_has_entity_name = True _attr_name = None def __init__(self, data, name, camera): From 2257e7454a564fd80c265c3c9e35fdc5c8044eb0 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 11 Jul 2023 20:15:16 +0200 Subject: [PATCH 035/154] Remove unreferenced issues (#96264) * Remove unreferenced issues * Remove outdated tests --- homeassistant/components/guardian/__init__.py | 40 ------------- .../components/guardian/strings.json | 13 ---- .../components/litterrobot/strings.json | 6 -- homeassistant/components/openuv/strings.json | 10 ---- .../components/unifiprotect/strings.json | 4 -- tests/components/unifiprotect/test_repairs.py | 60 +------------------ 6 files changed, 1 insertion(+), 132 deletions(-) diff --git a/homeassistant/components/guardian/__init__.py b/homeassistant/components/guardian/__init__.py index f587ef2e54ca38..ec8bd818d38874 100644 --- a/homeassistant/components/guardian/__init__.py +++ b/homeassistant/components/guardian/__init__.py @@ -25,7 +25,6 @@ from homeassistant.helpers import config_validation as cv, device_registry as dr from homeassistant.helpers.dispatcher import async_dispatcher_send from homeassistant.helpers.entity import DeviceInfo, EntityDescription -from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue from homeassistant.helpers.update_coordinator import CoordinatorEntity from .const import ( @@ -107,45 +106,6 @@ def async_get_entry_id_for_service_call(hass: HomeAssistant, call: ServiceCall) raise ValueError(f"No config entry for device ID: {device_id}") -@callback -def async_log_deprecated_service_call( - hass: HomeAssistant, - call: ServiceCall, - alternate_service: str, - alternate_target: str, - breaks_in_ha_version: str, -) -> None: - """Log a warning about a deprecated service call.""" - deprecated_service = f"{call.domain}.{call.service}" - - async_create_issue( - hass, - DOMAIN, - f"deprecated_service_{deprecated_service}", - breaks_in_ha_version=breaks_in_ha_version, - is_fixable=True, - is_persistent=True, - severity=IssueSeverity.WARNING, - translation_key="deprecated_service", - translation_placeholders={ - "alternate_service": alternate_service, - "alternate_target": alternate_target, - "deprecated_service": deprecated_service, - }, - ) - - LOGGER.warning( - ( - 'The "%s" service is deprecated and will be removed in %s; use the "%s" ' - 'service and pass it a target entity ID of "%s"' - ), - deprecated_service, - breaks_in_ha_version, - alternate_service, - alternate_target, - ) - - async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Elexa Guardian from a config entry.""" client = Client(entry.data[CONF_IP_ADDRESS], port=entry.data[CONF_PORT]) diff --git a/homeassistant/components/guardian/strings.json b/homeassistant/components/guardian/strings.json index dc3e6f4c17df50..ec2ad8d77cca71 100644 --- a/homeassistant/components/guardian/strings.json +++ b/homeassistant/components/guardian/strings.json @@ -18,19 +18,6 @@ "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]" } }, - "issues": { - "deprecated_service": { - "title": "The {deprecated_service} service will be removed", - "fix_flow": { - "step": { - "confirm": { - "title": "The {deprecated_service} service will be removed", - "description": "Update any automations or scripts that use this service to instead use the `{alternate_service}` service with a target entity ID of `{alternate_target}`." - } - } - } - } - }, "entity": { "binary_sensor": { "leak": { diff --git a/homeassistant/components/litterrobot/strings.json b/homeassistant/components/litterrobot/strings.json index 00a8a6122db998..5a6a0bf6998f38 100644 --- a/homeassistant/components/litterrobot/strings.json +++ b/homeassistant/components/litterrobot/strings.json @@ -25,12 +25,6 @@ "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" } }, - "issues": { - "migrated_attributes": { - "title": "Litter-Robot attributes are now their own sensors", - "description": "The vacuum entity attributes are now available as diagnostic sensors.\n\nPlease adjust any automations or scripts you may have that use these attributes." - } - }, "entity": { "binary_sensor": { "sleeping": { diff --git a/homeassistant/components/openuv/strings.json b/homeassistant/components/openuv/strings.json index 4aa29d11fcf26c..2534622975c5fc 100644 --- a/homeassistant/components/openuv/strings.json +++ b/homeassistant/components/openuv/strings.json @@ -37,16 +37,6 @@ } } }, - "issues": { - "deprecated_service_multiple_alternate_targets": { - "title": "The {deprecated_service} service is being removed", - "description": "Update any automations or scripts that use this service to instead use the `{alternate_service}` service with one of these entity IDs as the target: `{alternate_targets}`." - }, - "deprecated_service_single_alternate_target": { - "title": "The {deprecated_service} service is being removed", - "description": "Update any automations or scripts that use this service to instead use the `{alternate_service}` service with `{alternate_targets}` as the target." - } - }, "entity": { "binary_sensor": { "protection_window": { diff --git a/homeassistant/components/unifiprotect/strings.json b/homeassistant/components/unifiprotect/strings.json index fc50e8141a1660..b7be12233df742 100644 --- a/homeassistant/components/unifiprotect/strings.json +++ b/homeassistant/components/unifiprotect/strings.json @@ -75,10 +75,6 @@ "ea_setup_failed": { "title": "Setup error using Early Access version", "description": "You are using v{version} of UniFi Protect which is an Early Access version. An unrecoverable error occurred while trying to load the integration. Please [downgrade to a stable version](https://www.home-assistant.io/integrations/unifiprotect#downgrading-unifi-protect) of UniFi Protect to continue using the integration.\n\nError: {error}" - }, - "deprecate_smart_sensor": { - "title": "Smart Detection Sensor Deprecated", - "description": "The unified \"Detected Object\" sensor for smart detections is now deprecated. It has been replaced with individual smart detection binary sensors for each smart detection type.\n\nBelow are the detected automations or scripts that use one or more of the deprecated entities:\n{items}\nThe above list may be incomplete and it does not include any template usages inside of dashboards. Please update any templates, automations or scripts accordingly." } }, "entity": { diff --git a/tests/components/unifiprotect/test_repairs.py b/tests/components/unifiprotect/test_repairs.py index b9fa9bc57b8213..f68ebd9c8c65f8 100644 --- a/tests/components/unifiprotect/test_repairs.py +++ b/tests/components/unifiprotect/test_repairs.py @@ -5,7 +5,7 @@ from http import HTTPStatus from unittest.mock import Mock -from pyunifiprotect.data import Camera, Version +from pyunifiprotect.data import Version from homeassistant.components.repairs.issue_handler import ( async_process_repairs_platforms, @@ -15,9 +15,7 @@ RepairsFlowResourceView, ) from homeassistant.components.unifiprotect.const import DOMAIN -from homeassistant.const import Platform from homeassistant.core import HomeAssistant -from homeassistant.helpers import entity_registry as er from .utils import MockUFPFixture, init_entry @@ -127,59 +125,3 @@ async def test_ea_warning_fix( data = await resp.json() assert data["type"] == "create_entry" - - -async def test_deprecate_smart_default( - hass: HomeAssistant, - ufp: MockUFPFixture, - hass_ws_client: WebSocketGenerator, - doorbell: Camera, -) -> None: - """Test Deprecate Sensor repair does not exist by default (new installs).""" - - await init_entry(hass, ufp, [doorbell]) - - await async_process_repairs_platforms(hass) - ws_client = await hass_ws_client(hass) - - await ws_client.send_json({"id": 1, "type": "repairs/list_issues"}) - msg = await ws_client.receive_json() - - assert msg["success"] - issue = None - for i in msg["result"]["issues"]: - if i["issue_id"] == "deprecate_smart_sensor": - issue = i - assert issue is None - - -async def test_deprecate_smart_no_automations( - hass: HomeAssistant, - ufp: MockUFPFixture, - hass_ws_client: WebSocketGenerator, - doorbell: Camera, -) -> None: - """Test Deprecate Sensor repair exists for existing installs.""" - - registry = er.async_get(hass) - registry.async_get_or_create( - Platform.SENSOR, - DOMAIN, - f"{doorbell.mac}_detected_object", - config_entry=ufp.entry, - ) - - await init_entry(hass, ufp, [doorbell]) - - await async_process_repairs_platforms(hass) - ws_client = await hass_ws_client(hass) - - await ws_client.send_json({"id": 1, "type": "repairs/list_issues"}) - msg = await ws_client.receive_json() - - assert msg["success"] - issue = None - for i in msg["result"]["issues"]: - if i["issue_id"] == "deprecate_smart_sensor": - issue = i - assert issue is None From a7edf0a6081edca28c4f027ac592ab5fb4ef2970 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Tue, 11 Jul 2023 20:16:24 +0200 Subject: [PATCH 036/154] Add entity translations to Ukraine Alarm (#96260) * Add entity translations to Ukraine Alarm * Add entity translations to Ukraine Alarm --- .../components/ukraine_alarm/binary_sensor.py | 14 ++++++------ .../components/ukraine_alarm/strings.json | 22 +++++++++++++++++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/ukraine_alarm/binary_sensor.py b/homeassistant/components/ukraine_alarm/binary_sensor.py index 3cfe79ef5fb23c..eb83fe490e7029 100644 --- a/homeassistant/components/ukraine_alarm/binary_sensor.py +++ b/homeassistant/components/ukraine_alarm/binary_sensor.py @@ -30,36 +30,36 @@ BINARY_SENSOR_TYPES: tuple[BinarySensorEntityDescription, ...] = ( BinarySensorEntityDescription( key=ALERT_TYPE_UNKNOWN, - name="Unknown", + translation_key="unknown", device_class=BinarySensorDeviceClass.SAFETY, ), BinarySensorEntityDescription( key=ALERT_TYPE_AIR, - name="Air", + translation_key="air", device_class=BinarySensorDeviceClass.SAFETY, icon="mdi:cloud", ), BinarySensorEntityDescription( key=ALERT_TYPE_URBAN_FIGHTS, - name="Urban Fights", + translation_key="urban_fights", device_class=BinarySensorDeviceClass.SAFETY, icon="mdi:pistol", ), BinarySensorEntityDescription( key=ALERT_TYPE_ARTILLERY, - name="Artillery", + translation_key="artillery", device_class=BinarySensorDeviceClass.SAFETY, icon="mdi:tank", ), BinarySensorEntityDescription( key=ALERT_TYPE_CHEMICAL, - name="Chemical", + translation_key="chemical", device_class=BinarySensorDeviceClass.SAFETY, icon="mdi:chemical-weapon", ), BinarySensorEntityDescription( key=ALERT_TYPE_NUCLEAR, - name="Nuclear", + translation_key="nuclear", device_class=BinarySensorDeviceClass.SAFETY, icon="mdi:nuke", ), @@ -92,6 +92,7 @@ class UkraineAlarmSensor( """Class for a Ukraine Alarm binary sensor.""" _attr_attribution = ATTRIBUTION + _attr_has_entity_name = True def __init__( self, @@ -105,7 +106,6 @@ def __init__( self.entity_description = description - self._attr_name = f"{name} {description.name}" self._attr_unique_id = f"{unique_id}-{description.key}".lower() self._attr_device_info = DeviceInfo( entry_type=DeviceEntryType.SERVICE, diff --git a/homeassistant/components/ukraine_alarm/strings.json b/homeassistant/components/ukraine_alarm/strings.json index 6831d66adb3657..73a2657065ebf9 100644 --- a/homeassistant/components/ukraine_alarm/strings.json +++ b/homeassistant/components/ukraine_alarm/strings.json @@ -28,5 +28,27 @@ "description": "If you want to monitor not only state and district, choose its specific community" } } + }, + "entity": { + "binary_sensor": { + "unknown": { + "name": "Unknown" + }, + "air": { + "name": "Air" + }, + "urban_fights": { + "name": "Urban fights" + }, + "artillery": { + "name": "Artillery" + }, + "chemical": { + "name": "Chemical" + }, + "nuclear": { + "name": "Nuclear" + } + } } } From e9f76ed3d313a6cb905a96b981d8018b85e29bba Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 20:16:43 +0200 Subject: [PATCH 037/154] Update orjson to 3.9.2 (#96257) --- homeassistant/package_constraints.txt | 2 +- pyproject.toml | 2 +- requirements.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 16b25353183347..b82a7315648f40 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -30,7 +30,7 @@ janus==1.0.0 Jinja2==3.1.2 lru-dict==1.2.0 mutagen==1.46.0 -orjson==3.9.1 +orjson==3.9.2 paho-mqtt==1.6.1 Pillow==10.0.0 pip>=21.3.1,<23.2 diff --git a/pyproject.toml b/pyproject.toml index 8256ce2d06060d..f746797277308a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,7 @@ dependencies = [ "cryptography==41.0.1", # pyOpenSSL 23.2.0 is required to work with cryptography 41+ "pyOpenSSL==23.2.0", - "orjson==3.9.1", + "orjson==3.9.2", "pip>=21.3.1,<23.2", "python-slugify==4.0.1", "PyYAML==6.0", diff --git a/requirements.txt b/requirements.txt index 31e5812dadf759..210bd8a0bfc348 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,7 +18,7 @@ lru-dict==1.2.0 PyJWT==2.7.0 cryptography==41.0.1 pyOpenSSL==23.2.0 -orjson==3.9.1 +orjson==3.9.2 pip>=21.3.1,<23.2 python-slugify==4.0.1 PyYAML==6.0 From fe6402ef7357348aac5d8108a3180e682ce0a204 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Tue, 11 Jul 2023 20:19:04 +0200 Subject: [PATCH 038/154] Use device class naming for sfr box (#96092) --- homeassistant/components/sfr_box/button.py | 1 - homeassistant/components/sfr_box/sensor.py | 2 -- homeassistant/components/sfr_box/strings.json | 11 ----------- tests/components/sfr_box/snapshots/test_button.ambr | 2 +- tests/components/sfr_box/snapshots/test_sensor.ambr | 4 ++-- 5 files changed, 3 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/sfr_box/button.py b/homeassistant/components/sfr_box/button.py index ab987944acc116..13a1563034f274 100644 --- a/homeassistant/components/sfr_box/button.py +++ b/homeassistant/components/sfr_box/button.py @@ -67,7 +67,6 @@ class SFRBoxButtonEntityDescription(ButtonEntityDescription, SFRBoxButtonMixin): device_class=ButtonDeviceClass.RESTART, entity_category=EntityCategory.CONFIG, key="system_reboot", - translation_key="reboot", ), ) diff --git a/homeassistant/components/sfr_box/sensor.py b/homeassistant/components/sfr_box/sensor.py index fa754bbe62f1dd..c01d298daffdd4 100644 --- a/homeassistant/components/sfr_box/sensor.py +++ b/homeassistant/components/sfr_box/sensor.py @@ -180,7 +180,6 @@ class SFRBoxSensorEntityDescription(SensorEntityDescription, SFRBoxSensorMixin[_ entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, native_unit_of_measurement=UnitOfElectricPotential.MILLIVOLT, - translation_key="voltage", value_fn=lambda x: x.alimvoltage, ), SFRBoxSensorEntityDescription[SystemInfo]( @@ -189,7 +188,6 @@ class SFRBoxSensorEntityDescription(SensorEntityDescription, SFRBoxSensorMixin[_ entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, native_unit_of_measurement=UnitOfTemperature.CELSIUS, - translation_key="temperature", value_fn=lambda x: x.temperature / 1000, ), ) diff --git a/homeassistant/components/sfr_box/strings.json b/homeassistant/components/sfr_box/strings.json index cf74e9eb656ceb..3fc9691cc12f47 100644 --- a/homeassistant/components/sfr_box/strings.json +++ b/homeassistant/components/sfr_box/strings.json @@ -42,11 +42,6 @@ "name": "WAN status" } }, - "button": { - "reboot": { - "name": "[%key:component::button::entity_component::restart::name%]" - } - }, "sensor": { "dsl_attenuation_down": { "name": "DSL attenuation down" @@ -110,12 +105,6 @@ "unknown": "Unknown" } }, - "temperature": { - "name": "[%key:component::sensor::entity_component::temperature::name%]" - }, - "voltage": { - "name": "[%key:component::sensor::entity_component::voltage::name%]" - }, "wan_mode": { "name": "WAN mode", "state": { diff --git a/tests/components/sfr_box/snapshots/test_button.ambr b/tests/components/sfr_box/snapshots/test_button.ambr index dc6ccc1f25d1ec..f362cfc146fd3a 100644 --- a/tests/components/sfr_box/snapshots/test_button.ambr +++ b/tests/components/sfr_box/snapshots/test_button.ambr @@ -54,7 +54,7 @@ 'original_name': 'Restart', 'platform': 'sfr_box', 'supported_features': 0, - 'translation_key': 'reboot', + 'translation_key': None, 'unique_id': 'e4:5d:51:00:11:22_system_reboot', 'unit_of_measurement': None, }), diff --git a/tests/components/sfr_box/snapshots/test_sensor.ambr b/tests/components/sfr_box/snapshots/test_sensor.ambr index 2390ba625eb3ff..171a5803ada9c1 100644 --- a/tests/components/sfr_box/snapshots/test_sensor.ambr +++ b/tests/components/sfr_box/snapshots/test_sensor.ambr @@ -89,7 +89,7 @@ 'original_name': 'Voltage', 'platform': 'sfr_box', 'supported_features': 0, - 'translation_key': 'voltage', + 'translation_key': None, 'unique_id': 'e4:5d:51:00:11:22_system_alimvoltage', 'unit_of_measurement': , }), @@ -117,7 +117,7 @@ 'original_name': 'Temperature', 'platform': 'sfr_box', 'supported_features': 0, - 'translation_key': 'temperature', + 'translation_key': None, 'unique_id': 'e4:5d:51:00:11:22_system_temperature', 'unit_of_measurement': , }), From dfad1a920f3c12857a3610ccf382178b95feba8c Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Tue, 11 Jul 2023 20:19:51 +0200 Subject: [PATCH 039/154] Add entity translations to solarlog (#96157) --- homeassistant/components/solarlog/sensor.py | 44 ++++++------ .../components/solarlog/strings.json | 70 +++++++++++++++++++ 2 files changed, 92 insertions(+), 22 deletions(-) diff --git a/homeassistant/components/solarlog/sensor.py b/homeassistant/components/solarlog/sensor.py index 906d9aee629a85..a69d2a4c3829bf 100644 --- a/homeassistant/components/solarlog/sensor.py +++ b/homeassistant/components/solarlog/sensor.py @@ -36,13 +36,13 @@ class SolarLogSensorEntityDescription(SensorEntityDescription): SENSOR_TYPES: tuple[SolarLogSensorEntityDescription, ...] = ( SolarLogSensorEntityDescription( key="time", - name="last update", + translation_key="last_update", device_class=SensorDeviceClass.TIMESTAMP, value=as_local, ), SolarLogSensorEntityDescription( key="power_ac", - name="power AC", + translation_key="power_ac", icon="mdi:solar-power", native_unit_of_measurement=UnitOfPower.WATT, device_class=SensorDeviceClass.POWER, @@ -50,7 +50,7 @@ class SolarLogSensorEntityDescription(SensorEntityDescription): ), SolarLogSensorEntityDescription( key="power_dc", - name="power DC", + translation_key="power_dc", icon="mdi:solar-power", native_unit_of_measurement=UnitOfPower.WATT, device_class=SensorDeviceClass.POWER, @@ -58,21 +58,21 @@ class SolarLogSensorEntityDescription(SensorEntityDescription): ), SolarLogSensorEntityDescription( key="voltage_ac", - name="voltage AC", + translation_key="voltage_ac", native_unit_of_measurement=UnitOfElectricPotential.VOLT, device_class=SensorDeviceClass.VOLTAGE, state_class=SensorStateClass.MEASUREMENT, ), SolarLogSensorEntityDescription( key="voltage_dc", - name="voltage DC", + translation_key="voltage_dc", native_unit_of_measurement=UnitOfElectricPotential.VOLT, device_class=SensorDeviceClass.VOLTAGE, state_class=SensorStateClass.MEASUREMENT, ), SolarLogSensorEntityDescription( key="yield_day", - name="yield day", + translation_key="yield_day", icon="mdi:solar-power", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, @@ -80,7 +80,7 @@ class SolarLogSensorEntityDescription(SensorEntityDescription): ), SolarLogSensorEntityDescription( key="yield_yesterday", - name="yield yesterday", + translation_key="yield_yesterday", icon="mdi:solar-power", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, @@ -88,7 +88,7 @@ class SolarLogSensorEntityDescription(SensorEntityDescription): ), SolarLogSensorEntityDescription( key="yield_month", - name="yield month", + translation_key="yield_month", icon="mdi:solar-power", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, @@ -96,7 +96,7 @@ class SolarLogSensorEntityDescription(SensorEntityDescription): ), SolarLogSensorEntityDescription( key="yield_year", - name="yield year", + translation_key="yield_year", icon="mdi:solar-power", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, @@ -104,7 +104,7 @@ class SolarLogSensorEntityDescription(SensorEntityDescription): ), SolarLogSensorEntityDescription( key="yield_total", - name="yield total", + translation_key="yield_total", icon="mdi:solar-power", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, @@ -113,42 +113,42 @@ class SolarLogSensorEntityDescription(SensorEntityDescription): ), SolarLogSensorEntityDescription( key="consumption_ac", - name="consumption AC", + translation_key="consumption_ac", native_unit_of_measurement=UnitOfPower.WATT, device_class=SensorDeviceClass.POWER, state_class=SensorStateClass.MEASUREMENT, ), SolarLogSensorEntityDescription( key="consumption_day", - name="consumption day", + translation_key="consumption_day", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, value=lambda value: round(value / 1000, 3), ), SolarLogSensorEntityDescription( key="consumption_yesterday", - name="consumption yesterday", + translation_key="consumption_yesterday", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, value=lambda value: round(value / 1000, 3), ), SolarLogSensorEntityDescription( key="consumption_month", - name="consumption month", + translation_key="consumption_month", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, value=lambda value: round(value / 1000, 3), ), SolarLogSensorEntityDescription( key="consumption_year", - name="consumption year", + translation_key="consumption_year", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, value=lambda value: round(value / 1000, 3), ), SolarLogSensorEntityDescription( key="consumption_total", - name="consumption total", + translation_key="consumption_total", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL, @@ -156,14 +156,14 @@ class SolarLogSensorEntityDescription(SensorEntityDescription): ), SolarLogSensorEntityDescription( key="total_power", - name="installed peak power", + translation_key="total_power", icon="mdi:solar-power", native_unit_of_measurement=UnitOfPower.WATT, device_class=SensorDeviceClass.POWER, ), SolarLogSensorEntityDescription( key="alternator_loss", - name="alternator loss", + translation_key="alternator_loss", icon="mdi:solar-power", native_unit_of_measurement=UnitOfPower.WATT, device_class=SensorDeviceClass.POWER, @@ -171,7 +171,7 @@ class SolarLogSensorEntityDescription(SensorEntityDescription): ), SolarLogSensorEntityDescription( key="capacity", - name="capacity", + translation_key="capacity", icon="mdi:solar-power", native_unit_of_measurement=PERCENTAGE, device_class=SensorDeviceClass.POWER_FACTOR, @@ -180,7 +180,7 @@ class SolarLogSensorEntityDescription(SensorEntityDescription): ), SolarLogSensorEntityDescription( key="efficiency", - name="efficiency", + translation_key="efficiency", native_unit_of_measurement=PERCENTAGE, device_class=SensorDeviceClass.POWER_FACTOR, state_class=SensorStateClass.MEASUREMENT, @@ -188,7 +188,7 @@ class SolarLogSensorEntityDescription(SensorEntityDescription): ), SolarLogSensorEntityDescription( key="power_available", - name="power available", + translation_key="power_available", icon="mdi:solar-power", native_unit_of_measurement=UnitOfPower.WATT, device_class=SensorDeviceClass.POWER, @@ -196,7 +196,7 @@ class SolarLogSensorEntityDescription(SensorEntityDescription): ), SolarLogSensorEntityDescription( key="usage", - name="usage", + translation_key="usage", native_unit_of_measurement=PERCENTAGE, device_class=SensorDeviceClass.POWER_FACTOR, state_class=SensorStateClass.MEASUREMENT, diff --git a/homeassistant/components/solarlog/strings.json b/homeassistant/components/solarlog/strings.json index 068132dea41b9f..62e923a766dbdf 100644 --- a/homeassistant/components/solarlog/strings.json +++ b/homeassistant/components/solarlog/strings.json @@ -16,5 +16,75 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" } + }, + "entity": { + "sensor": { + "last_update": { + "name": "Last update" + }, + "power_ac": { + "name": "Power AC" + }, + "power_dc": { + "name": "Power DC" + }, + "voltage_ac": { + "name": "Voltage AC" + }, + "voltage_dc": { + "name": "Voltage DC" + }, + "yield_day": { + "name": "Yield day" + }, + "yield_yesterday": { + "name": "Yield yesterday" + }, + "yield_month": { + "name": "Yield month" + }, + "yield_year": { + "name": "Yield year" + }, + "yield_total": { + "name": "Yield total" + }, + "consumption_ac": { + "name": "Consumption AC" + }, + "consumption_day": { + "name": "Consumption day" + }, + "consumption_yesterday": { + "name": "Consumption yesterday" + }, + "consumption_month": { + "name": "Consumption month" + }, + "consumption_year": { + "name": "Consumption year" + }, + "consumption_total": { + "name": "Consumption total" + }, + "total_power": { + "name": "Installed peak power" + }, + "alternator_loss": { + "name": "Alternator loss" + }, + "capacity": { + "name": "Capacity" + }, + "efficiency": { + "name": "Efficiency" + }, + "power_available": { + "name": "Power available" + }, + "usage": { + "name": "Usage" + } + } } } From efcaad1179cf4b642707378d93a3f3951400564b Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Tue, 11 Jul 2023 20:22:12 +0200 Subject: [PATCH 040/154] Fix handling MQTT light brightness from zero rgb (#96286) * Fix handling MQTT light brightness from zero rgb * Fix log message --- homeassistant/components/mqtt/light/schema_basic.py | 7 +++++++ tests/components/mqtt/test_light.py | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/homeassistant/components/mqtt/light/schema_basic.py b/homeassistant/components/mqtt/light/schema_basic.py index 7f2c2cf5e06abe..fe09667ca4aaa1 100644 --- a/homeassistant/components/mqtt/light/schema_basic.py +++ b/homeassistant/components/mqtt/light/schema_basic.py @@ -482,6 +482,13 @@ def _rgbx_received( if self._topic[CONF_BRIGHTNESS_STATE_TOPIC] is None: rgb = convert_color(*color) brightness = max(rgb) + if brightness == 0: + _LOGGER.debug( + "Ignoring %s message with zero rgb brightness from '%s'", + color_mode, + msg.topic, + ) + return None self._attr_brightness = brightness # Normalize the color to 100% brightness color = tuple( diff --git a/tests/components/mqtt/test_light.py b/tests/components/mqtt/test_light.py index ee4f170e8e675d..59d5090b7118da 100644 --- a/tests/components/mqtt/test_light.py +++ b/tests/components/mqtt/test_light.py @@ -666,6 +666,12 @@ async def test_brightness_from_rgb_controlling_scale( assert state.attributes.get("brightness") == 128 assert state.attributes.get("rgb_color") == (255, 128, 64) + # Test zero rgb is ignored + async_fire_mqtt_message(hass, "test_scale_rgb/rgb/status", "0,0,0") + state = hass.states.get("light.test") + assert state.attributes.get("brightness") == 128 + assert state.attributes.get("rgb_color") == (255, 128, 64) + mqtt_mock.async_publish.reset_mock() await common.async_turn_on(hass, "light.test", brightness=191) await hass.async_block_till_done() From fe44827e3c6d7bb2620673833d64d541a2e4b58d Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Tue, 11 Jul 2023 20:24:33 +0200 Subject: [PATCH 041/154] Add entity translations to Rainforest eagle (#96031) * Add entity translations to Rainforest eagle * Add entity translations to Rainforest Eagle --- .../components/rainforest_eagle/sensor.py | 11 ++++++----- .../components/rainforest_eagle/strings.json | 16 ++++++++++++++++ tests/components/rainforest_eagle/test_sensor.py | 8 ++++---- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/rainforest_eagle/sensor.py b/homeassistant/components/rainforest_eagle/sensor.py index 0680aa7455d1b0..a7fd27a051fb34 100644 --- a/homeassistant/components/rainforest_eagle/sensor.py +++ b/homeassistant/components/rainforest_eagle/sensor.py @@ -21,22 +21,21 @@ SENSORS = ( SensorEntityDescription( key="zigbee:InstantaneousDemand", - # We can drop the "Eagle-200" part of the name in HA 2021.12 - name="Eagle-200 Meter Power Demand", + translation_key="power_demand", native_unit_of_measurement=UnitOfPower.KILO_WATT, device_class=SensorDeviceClass.POWER, state_class=SensorStateClass.MEASUREMENT, ), SensorEntityDescription( key="zigbee:CurrentSummationDelivered", - name="Eagle-200 Total Meter Energy Delivered", + translation_key="total_energy_delivered", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, ), SensorEntityDescription( key="zigbee:CurrentSummationReceived", - name="Eagle-200 Total Meter Energy Received", + translation_key="total_energy_received", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, @@ -57,7 +56,7 @@ async def async_setup_entry( coordinator, SensorEntityDescription( key="zigbee:Price", - name="Meter Price", + translation_key="meter_price", native_unit_of_measurement=f"{coordinator.data['zigbee:PriceCurrency']}/{UnitOfEnergy.KILO_WATT_HOUR}", state_class=SensorStateClass.MEASUREMENT, ), @@ -70,6 +69,8 @@ async def async_setup_entry( class EagleSensor(CoordinatorEntity[EagleDataCoordinator], SensorEntity): """Implementation of the Rainforest Eagle sensor.""" + _attr_has_entity_name = True + def __init__(self, coordinator, entity_description): """Initialize the sensor.""" super().__init__(coordinator) diff --git a/homeassistant/components/rainforest_eagle/strings.json b/homeassistant/components/rainforest_eagle/strings.json index b32f38302f486e..58c7f6bd795a37 100644 --- a/homeassistant/components/rainforest_eagle/strings.json +++ b/homeassistant/components/rainforest_eagle/strings.json @@ -17,5 +17,21 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" } + }, + "entity": { + "sensor": { + "power_demand": { + "name": "Meter power demand" + }, + "total_energy_delivered": { + "name": "Total meter energy delivered" + }, + "total_energy_received": { + "name": "Total meter energy received" + }, + "meter_price": { + "name": "Meter price" + } + } } } diff --git a/tests/components/rainforest_eagle/test_sensor.py b/tests/components/rainforest_eagle/test_sensor.py index 96b9e0a85dc94f..5e76a81932aff2 100644 --- a/tests/components/rainforest_eagle/test_sensor.py +++ b/tests/components/rainforest_eagle/test_sensor.py @@ -32,7 +32,7 @@ async def test_sensors_200(hass: HomeAssistant, setup_rainforest_200) -> None: assert len(hass.states.async_all()) == 4 - price = hass.states.get("sensor.meter_price") + price = hass.states.get("sensor.eagle_200_meter_price") assert price is not None assert price.state == "0.053990" assert price.attributes["unit_of_measurement"] == "USD/kWh" @@ -42,17 +42,17 @@ async def test_sensors_100(hass: HomeAssistant, setup_rainforest_100) -> None: """Test the sensors.""" assert len(hass.states.async_all()) == 3 - demand = hass.states.get("sensor.eagle_200_meter_power_demand") + demand = hass.states.get("sensor.eagle_100_meter_power_demand") assert demand is not None assert demand.state == "1.152000" assert demand.attributes["unit_of_measurement"] == "kW" - delivered = hass.states.get("sensor.eagle_200_total_meter_energy_delivered") + delivered = hass.states.get("sensor.eagle_100_total_meter_energy_delivered") assert delivered is not None assert delivered.state == "45251.285000" assert delivered.attributes["unit_of_measurement"] == "kWh" - received = hass.states.get("sensor.eagle_200_total_meter_energy_received") + received = hass.states.get("sensor.eagle_100_total_meter_energy_received") assert received is not None assert received.state == "232.232000" assert received.attributes["unit_of_measurement"] == "kWh" From 8b379254c33e8f0b8fbb76753488160f89035be5 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Tue, 11 Jul 2023 20:27:31 +0200 Subject: [PATCH 042/154] Migrate Roomba to has entity name (#96085) --- .../components/roomba/binary_sensor.py | 6 +--- .../components/roomba/irobot_base.py | 8 ++---- homeassistant/components/roomba/sensor.py | 28 ++----------------- homeassistant/components/roomba/strings.json | 7 +++++ 4 files changed, 13 insertions(+), 36 deletions(-) diff --git a/homeassistant/components/roomba/binary_sensor.py b/homeassistant/components/roomba/binary_sensor.py index 0acd655363f505..f480839388ca46 100644 --- a/homeassistant/components/roomba/binary_sensor.py +++ b/homeassistant/components/roomba/binary_sensor.py @@ -28,11 +28,7 @@ class RoombaBinStatus(IRobotEntity, BinarySensorEntity): """Class to hold Roomba Sensor basic info.""" ICON = "mdi:delete-variant" - - @property - def name(self): - """Return the name of the sensor.""" - return f"{self._name} Bin Full" + _attr_translation_key = "bin_full" @property def unique_id(self): diff --git a/homeassistant/components/roomba/irobot_base.py b/homeassistant/components/roomba/irobot_base.py index 317209886bd2b6..5dbd1e986f3f55 100644 --- a/homeassistant/components/roomba/irobot_base.py +++ b/homeassistant/components/roomba/irobot_base.py @@ -61,6 +61,7 @@ class IRobotEntity(Entity): """Base class for iRobot Entities.""" _attr_should_poll = False + _attr_has_entity_name = True def __init__(self, roomba, blid): """Initialize the iRobot handler.""" @@ -135,6 +136,8 @@ def on_message(self, json_data): class IRobotVacuum(IRobotEntity, StateVacuumEntity): """Base class for iRobot robots.""" + _attr_name = None + def __init__(self, roomba, blid): """Initialize the iRobot handler.""" super().__init__(roomba, blid) @@ -160,11 +163,6 @@ def available(self) -> bool: """Return True if entity is available.""" return True # Always available, otherwise setup will fail - @property - def name(self): - """Return the name of the device.""" - return self._name - @property def extra_state_attributes(self): """Return the state attributes of the device.""" diff --git a/homeassistant/components/roomba/sensor.py b/homeassistant/components/roomba/sensor.py index c0092922783ed5..dd74a023ff101d 100644 --- a/homeassistant/components/roomba/sensor.py +++ b/homeassistant/components/roomba/sensor.py @@ -1,11 +1,9 @@ """Sensor for checking the battery level of Roomba.""" from homeassistant.components.sensor import SensorDeviceClass, SensorEntity -from homeassistant.components.vacuum import STATE_DOCKED from homeassistant.config_entries import ConfigEntry from homeassistant.const import PERCENTAGE, EntityCategory from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.icon import icon_for_battery_level from .const import BLID, DOMAIN, ROOMBA_SESSION from .irobot_base import IRobotEntity @@ -28,36 +26,14 @@ class RoombaBattery(IRobotEntity, SensorEntity): """Class to hold Roomba Sensor basic info.""" _attr_entity_category = EntityCategory.DIAGNOSTIC - - @property - def name(self): - """Return the name of the sensor.""" - return f"{self._name} Battery Level" + _attr_device_class = SensorDeviceClass.BATTERY + _attr_native_unit_of_measurement = PERCENTAGE @property def unique_id(self): """Return the ID of this sensor.""" return f"battery_{self._blid}" - @property - def device_class(self): - """Return the device class of the sensor.""" - return SensorDeviceClass.BATTERY - - @property - def native_unit_of_measurement(self): - """Return the unit_of_measurement of the device.""" - return PERCENTAGE - - @property - def icon(self): - """Return the icon for the battery.""" - charging = bool(self._robot_state == STATE_DOCKED) - - return icon_for_battery_level( - battery_level=self._battery_level, charging=charging - ) - @property def native_value(self): """Return the state of the sensor.""" diff --git a/homeassistant/components/roomba/strings.json b/homeassistant/components/roomba/strings.json index be2e5b99159064..206e8c5bae0741 100644 --- a/homeassistant/components/roomba/strings.json +++ b/homeassistant/components/roomba/strings.json @@ -47,5 +47,12 @@ } } } + }, + "entity": { + "binary_sensor": { + "bin_full": { + "name": "Bin full" + } + } } } From 38823bae71103216bc692e103054c7a6c8ae2ab9 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 20:29:09 +0200 Subject: [PATCH 043/154] Update colorlog to 6.7.0 (#96131) --- homeassistant/scripts/check_config.py | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/scripts/check_config.py b/homeassistant/scripts/check_config.py index 92f5b442d9ed45..5384b86cb98fd3 100644 --- a/homeassistant/scripts/check_config.py +++ b/homeassistant/scripts/check_config.py @@ -26,7 +26,7 @@ # mypy: allow-untyped-calls, allow-untyped-defs -REQUIREMENTS = ("colorlog==6.6.0",) +REQUIREMENTS = ("colorlog==6.7.0",) _LOGGER = logging.getLogger(__name__) # pylint: disable=protected-access diff --git a/requirements_all.txt b/requirements_all.txt index f6d8a03cbe873f..27884a263f06ca 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -592,7 +592,7 @@ clx-sdk-xms==1.0.0 coinbase==2.1.0 # homeassistant.scripts.check_config -colorlog==6.6.0 +colorlog==6.7.0 # homeassistant.components.color_extractor colorthief==0.2.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index cd72a6df01b4a6..5210e0e335b340 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -481,7 +481,7 @@ caldav==1.2.0 coinbase==2.1.0 # homeassistant.scripts.check_config -colorlog==6.6.0 +colorlog==6.7.0 # homeassistant.components.color_extractor colorthief==0.2.1 From 05c194f36d8d0ac8ce312bfdaa9538b60ec59647 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 20:29:55 +0200 Subject: [PATCH 044/154] Upgrade pylint-per-file-ignore to v1.2.1 (#96134) --- requirements_test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_test.txt b/requirements_test.txt index e6c805a64c1ec1..11920917a5913f 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -15,7 +15,7 @@ mypy==1.4.1 pre-commit==3.1.0 pydantic==1.10.11 pylint==2.17.4 -pylint-per-file-ignores==1.1.0 +pylint-per-file-ignores==1.2.1 pipdeptree==2.9.4 pytest-asyncio==0.20.3 pytest-aiohttp==1.0.4 From ad091479ea1052db022ae10c04d65f8801b78ab3 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Tue, 11 Jul 2023 20:32:33 +0200 Subject: [PATCH 045/154] Cleanup unneeded MQTT vacuum feature check (#96312) --- homeassistant/components/mqtt/vacuum/schema_legacy.py | 4 ++-- homeassistant/components/mqtt/vacuum/schema_state.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/mqtt/vacuum/schema_legacy.py b/homeassistant/components/mqtt/vacuum/schema_legacy.py index 18cda0b137d91a..7c73e579112488 100644 --- a/homeassistant/components/mqtt/vacuum/schema_legacy.py +++ b/homeassistant/components/mqtt/vacuum/schema_legacy.py @@ -419,9 +419,9 @@ def battery_icon(self) -> str: ) async def _async_publish_command(self, feature: VacuumEntityFeature) -> None: - """Check for a missing feature or command topic.""" + """Publish a command.""" - if self._command_topic is None or self.supported_features & feature == 0: + if self._command_topic is None: return await self.async_publish( diff --git a/homeassistant/components/mqtt/vacuum/schema_state.py b/homeassistant/components/mqtt/vacuum/schema_state.py index fef185687db971..ee06131af0251d 100644 --- a/homeassistant/components/mqtt/vacuum/schema_state.py +++ b/homeassistant/components/mqtt/vacuum/schema_state.py @@ -259,8 +259,8 @@ async def _subscribe_topics(self) -> None: await subscription.async_subscribe_topics(self.hass, self._sub_state) async def _async_publish_command(self, feature: VacuumEntityFeature) -> None: - """Check for a missing feature or command topic.""" - if self._command_topic is None or self.supported_features & feature == 0: + """Publish a command.""" + if self._command_topic is None: return await self.async_publish( From 77ebf8a8e5cdfc939884c92c1d5d43a31b87ca92 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Tue, 11 Jul 2023 20:34:11 +0200 Subject: [PATCH 046/154] Add entity translations to Juicenet (#95487) --- homeassistant/components/juicenet/entity.py | 2 ++ homeassistant/components/juicenet/number.py | 4 +--- homeassistant/components/juicenet/sensor.py | 9 ++------- .../components/juicenet/strings.json | 20 +++++++++++++++++++ homeassistant/components/juicenet/switch.py | 7 ++----- 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/juicenet/entity.py b/homeassistant/components/juicenet/entity.py index 0f3811bef6f477..2f25a934e7f32e 100644 --- a/homeassistant/components/juicenet/entity.py +++ b/homeassistant/components/juicenet/entity.py @@ -14,6 +14,8 @@ class JuiceNetDevice(CoordinatorEntity): """Represent a base JuiceNet device.""" + _attr_has_entity_name = True + def __init__( self, device: Charger, key: str, coordinator: DataUpdateCoordinator ) -> None: diff --git a/homeassistant/components/juicenet/number.py b/homeassistant/components/juicenet/number.py index 45be1dd900495c..e78f6189baf90a 100644 --- a/homeassistant/components/juicenet/number.py +++ b/homeassistant/components/juicenet/number.py @@ -37,7 +37,7 @@ class JuiceNetNumberEntityDescription( NUMBER_TYPES: tuple[JuiceNetNumberEntityDescription, ...] = ( JuiceNetNumberEntityDescription( - name="Amperage Limit", + translation_key="amperage_limit", key="current_charging_amperage_limit", native_min_value=6, native_max_value_key="max_charging_amperage", @@ -80,8 +80,6 @@ def __init__( super().__init__(device, description.key, coordinator) self.entity_description = description - self._attr_name = f"{self.device.name} {description.name}" - @property def native_value(self) -> float | None: """Return the value of the entity.""" diff --git a/homeassistant/components/juicenet/sensor.py b/homeassistant/components/juicenet/sensor.py index fdc40211d775d8..5f71e066b9c24b 100644 --- a/homeassistant/components/juicenet/sensor.py +++ b/homeassistant/components/juicenet/sensor.py @@ -29,40 +29,36 @@ ), SensorEntityDescription( key="temperature", - name="Temperature", native_unit_of_measurement=UnitOfTemperature.CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, ), SensorEntityDescription( key="voltage", - name="Voltage", native_unit_of_measurement=UnitOfElectricPotential.VOLT, device_class=SensorDeviceClass.VOLTAGE, ), SensorEntityDescription( key="amps", - name="Amps", native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, device_class=SensorDeviceClass.CURRENT, state_class=SensorStateClass.MEASUREMENT, ), SensorEntityDescription( key="watts", - name="Watts", native_unit_of_measurement=UnitOfPower.WATT, device_class=SensorDeviceClass.POWER, state_class=SensorStateClass.MEASUREMENT, ), SensorEntityDescription( key="charge_time", - name="Charge time", + translation_key="charge_time", native_unit_of_measurement=UnitOfTime.SECONDS, icon="mdi:timer-outline", ), SensorEntityDescription( key="energy_added", - name="Energy added", + translation_key="energy_added", native_unit_of_measurement=UnitOfEnergy.WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, @@ -97,7 +93,6 @@ def __init__( """Initialise the sensor.""" super().__init__(device, description.key, coordinator) self.entity_description = description - self._attr_name = f"{self.device.name} {description.name}" @property def icon(self): diff --git a/homeassistant/components/juicenet/strings.json b/homeassistant/components/juicenet/strings.json index bc4a66e72d4361..0e3732c66d2bfa 100644 --- a/homeassistant/components/juicenet/strings.json +++ b/homeassistant/components/juicenet/strings.json @@ -17,5 +17,25 @@ "title": "Connect to JuiceNet" } } + }, + "entity": { + "number": { + "amperage_limit": { + "name": "Amperage limit" + } + }, + "sensor": { + "charge_time": { + "name": "Charge time" + }, + "energy_added": { + "name": "Energy added" + } + }, + "switch": { + "charge_now": { + "name": "Charge now" + } + } } } diff --git a/homeassistant/components/juicenet/switch.py b/homeassistant/components/juicenet/switch.py index 576c66c0841f6a..7c373eeeb245b7 100644 --- a/homeassistant/components/juicenet/switch.py +++ b/homeassistant/components/juicenet/switch.py @@ -29,15 +29,12 @@ async def async_setup_entry( class JuiceNetChargeNowSwitch(JuiceNetDevice, SwitchEntity): """Implementation of a JuiceNet switch.""" + _attr_translation_key = "charge_now" + def __init__(self, device, coordinator): """Initialise the switch.""" super().__init__(device, "charge_now", coordinator) - @property - def name(self): - """Return the name of the device.""" - return f"{self.device.name} Charge Now" - @property def is_on(self): """Return true if switch is on.""" From c431fc2297ebb1d5fd49c245e8f7a9028d4248b4 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 20:56:21 +0200 Subject: [PATCH 047/154] Migrate reload only helper services to support translations (#96344) --- homeassistant/components/bayesian/services.yaml | 2 -- homeassistant/components/bayesian/strings.json | 6 ++++++ homeassistant/components/filter/services.yaml | 2 -- homeassistant/components/filter/strings.json | 8 ++++++++ homeassistant/components/generic/services.yaml | 2 -- homeassistant/components/generic/strings.json | 6 ++++++ homeassistant/components/generic_thermostat/services.yaml | 2 -- homeassistant/components/generic_thermostat/strings.json | 8 ++++++++ homeassistant/components/history_stats/services.yaml | 2 -- homeassistant/components/history_stats/strings.json | 8 ++++++++ homeassistant/components/min_max/services.yaml | 2 -- homeassistant/components/min_max/strings.json | 6 ++++++ homeassistant/components/person/services.yaml | 2 -- homeassistant/components/person/strings.json | 6 ++++++ homeassistant/components/schedule/services.yaml | 2 -- homeassistant/components/schedule/strings.json | 6 ++++++ homeassistant/components/statistics/services.yaml | 2 -- homeassistant/components/statistics/strings.json | 8 ++++++++ homeassistant/components/trend/services.yaml | 2 -- homeassistant/components/trend/strings.json | 8 ++++++++ homeassistant/components/universal/services.yaml | 2 -- homeassistant/components/universal/strings.json | 8 ++++++++ homeassistant/components/zone/services.yaml | 2 -- homeassistant/components/zone/strings.json | 8 ++++++++ 24 files changed, 86 insertions(+), 24 deletions(-) create mode 100644 homeassistant/components/filter/strings.json create mode 100644 homeassistant/components/generic_thermostat/strings.json create mode 100644 homeassistant/components/history_stats/strings.json create mode 100644 homeassistant/components/statistics/strings.json create mode 100644 homeassistant/components/trend/strings.json create mode 100644 homeassistant/components/universal/strings.json create mode 100644 homeassistant/components/zone/strings.json diff --git a/homeassistant/components/bayesian/services.yaml b/homeassistant/components/bayesian/services.yaml index c1dc891805a3b7..c983a105c93977 100644 --- a/homeassistant/components/bayesian/services.yaml +++ b/homeassistant/components/bayesian/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload all bayesian entities diff --git a/homeassistant/components/bayesian/strings.json b/homeassistant/components/bayesian/strings.json index 338795624cd806..f7c12523b2c8c5 100644 --- a/homeassistant/components/bayesian/strings.json +++ b/homeassistant/components/bayesian/strings.json @@ -8,5 +8,11 @@ "description": "In the Bayesian integration `prob_given_false` is now a required configuration variable as there was no mathematical rationale for the previous default value. Please add this to your `configuration.yml` for `bayesian/{entity}`. These observations will be ignored until you do.", "title": "Manual YAML addition required for Bayesian" } + }, + "services": { + "reload": { + "name": "Reload", + "description": "Reloads bayesian sensors from the YAML-configuration." + } } } diff --git a/homeassistant/components/filter/services.yaml b/homeassistant/components/filter/services.yaml index 431c73616ceff7..c983a105c93977 100644 --- a/homeassistant/components/filter/services.yaml +++ b/homeassistant/components/filter/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload all filter entities diff --git a/homeassistant/components/filter/strings.json b/homeassistant/components/filter/strings.json new file mode 100644 index 00000000000000..078e5b35980def --- /dev/null +++ b/homeassistant/components/filter/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "reload": { + "name": "Reload", + "description": "Reloads filters from the YAML-configuration." + } + } +} diff --git a/homeassistant/components/generic/services.yaml b/homeassistant/components/generic/services.yaml index a05a9e3415daeb..c983a105c93977 100644 --- a/homeassistant/components/generic/services.yaml +++ b/homeassistant/components/generic/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload all generic entities. diff --git a/homeassistant/components/generic/strings.json b/homeassistant/components/generic/strings.json index 0ce8af4f3a6849..d23bb605c7b44e 100644 --- a/homeassistant/components/generic/strings.json +++ b/homeassistant/components/generic/strings.json @@ -83,5 +83,11 @@ "stream_io_error": "[%key:component::generic::config::error::stream_io_error%]", "stream_not_permitted": "[%key:component::generic::config::error::stream_not_permitted%]" } + }, + "services": { + "reload": { + "name": "Reload", + "description": "Reloads generic cameras from the YAML-configuration." + } } } diff --git a/homeassistant/components/generic_thermostat/services.yaml b/homeassistant/components/generic_thermostat/services.yaml index ef6745bd36f1f6..c983a105c93977 100644 --- a/homeassistant/components/generic_thermostat/services.yaml +++ b/homeassistant/components/generic_thermostat/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload all generic_thermostat entities. diff --git a/homeassistant/components/generic_thermostat/strings.json b/homeassistant/components/generic_thermostat/strings.json new file mode 100644 index 00000000000000..f1525b2516da05 --- /dev/null +++ b/homeassistant/components/generic_thermostat/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "reload": { + "name": "Reload", + "description": "Reloads generic thermostats from the YAML-configuration." + } + } +} diff --git a/homeassistant/components/history_stats/services.yaml b/homeassistant/components/history_stats/services.yaml index f254295ea20252..c983a105c93977 100644 --- a/homeassistant/components/history_stats/services.yaml +++ b/homeassistant/components/history_stats/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload all history_stats entities. diff --git a/homeassistant/components/history_stats/strings.json b/homeassistant/components/history_stats/strings.json new file mode 100644 index 00000000000000..cb4601f2a096b6 --- /dev/null +++ b/homeassistant/components/history_stats/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "reload": { + "name": "Reload", + "description": "Reloads history stats sensors from the YAML-configuration." + } + } +} diff --git a/homeassistant/components/min_max/services.yaml b/homeassistant/components/min_max/services.yaml index cca67d921444c1..c983a105c93977 100644 --- a/homeassistant/components/min_max/services.yaml +++ b/homeassistant/components/min_max/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload all min_max entities. diff --git a/homeassistant/components/min_max/strings.json b/homeassistant/components/min_max/strings.json index c76a6faf2f5981..464d01b90b4c91 100644 --- a/homeassistant/components/min_max/strings.json +++ b/homeassistant/components/min_max/strings.json @@ -43,5 +43,11 @@ "sum": "Sum" } } + }, + "services": { + "reload": { + "name": "Reload", + "description": "Reloads min/max sensors from the YAML-configuration." + } } } diff --git a/homeassistant/components/person/services.yaml b/homeassistant/components/person/services.yaml index 265c6049563dfb..c983a105c93977 100644 --- a/homeassistant/components/person/services.yaml +++ b/homeassistant/components/person/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload the person configuration. diff --git a/homeassistant/components/person/strings.json b/homeassistant/components/person/strings.json index 8a8915541d8305..10a982535f2f02 100644 --- a/homeassistant/components/person/strings.json +++ b/homeassistant/components/person/strings.json @@ -25,5 +25,11 @@ } } } + }, + "services": { + "reload": { + "name": "Reload", + "description": "Reloads persons from the YAML-configuration." + } } } diff --git a/homeassistant/components/schedule/services.yaml b/homeassistant/components/schedule/services.yaml index b34dd5e83da469..c983a105c93977 100644 --- a/homeassistant/components/schedule/services.yaml +++ b/homeassistant/components/schedule/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload the schedule configuration diff --git a/homeassistant/components/schedule/strings.json b/homeassistant/components/schedule/strings.json index 4c22e5ecead342..aea07cc3ff26c6 100644 --- a/homeassistant/components/schedule/strings.json +++ b/homeassistant/components/schedule/strings.json @@ -20,5 +20,11 @@ } } } + }, + "services": { + "reload": { + "name": "Reload", + "description": "Reloads schedules from the YAML-configuration." + } } } diff --git a/homeassistant/components/statistics/services.yaml b/homeassistant/components/statistics/services.yaml index 8c2c8f8464aa83..c983a105c93977 100644 --- a/homeassistant/components/statistics/services.yaml +++ b/homeassistant/components/statistics/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload all statistics entities. diff --git a/homeassistant/components/statistics/strings.json b/homeassistant/components/statistics/strings.json new file mode 100644 index 00000000000000..6b2a04a85df497 --- /dev/null +++ b/homeassistant/components/statistics/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "reload": { + "name": "Reload", + "description": "Reloads statistics sensors from the YAML-configuration." + } + } +} diff --git a/homeassistant/components/trend/services.yaml b/homeassistant/components/trend/services.yaml index 1d29e08dccf795..c983a105c93977 100644 --- a/homeassistant/components/trend/services.yaml +++ b/homeassistant/components/trend/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload all trend entities. diff --git a/homeassistant/components/trend/strings.json b/homeassistant/components/trend/strings.json new file mode 100644 index 00000000000000..1715f019f272d6 --- /dev/null +++ b/homeassistant/components/trend/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "reload": { + "name": "Reload", + "description": "Reloads trend sensors from the YAML-configuration." + } + } +} diff --git a/homeassistant/components/universal/services.yaml b/homeassistant/components/universal/services.yaml index e0af28bf3a608c..c983a105c93977 100644 --- a/homeassistant/components/universal/services.yaml +++ b/homeassistant/components/universal/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload all universal entities diff --git a/homeassistant/components/universal/strings.json b/homeassistant/components/universal/strings.json new file mode 100644 index 00000000000000..b440d76ebc23ab --- /dev/null +++ b/homeassistant/components/universal/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "reload": { + "name": "Reload", + "description": "Reloads universal media players from the YAML-configuration." + } + } +} diff --git a/homeassistant/components/zone/services.yaml b/homeassistant/components/zone/services.yaml index 2ce77132a532c6..c983a105c93977 100644 --- a/homeassistant/components/zone/services.yaml +++ b/homeassistant/components/zone/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload the YAML-based zone configuration. diff --git a/homeassistant/components/zone/strings.json b/homeassistant/components/zone/strings.json new file mode 100644 index 00000000000000..b2f3b5efffa92e --- /dev/null +++ b/homeassistant/components/zone/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "reload": { + "name": "Reload", + "description": "Reloads zones from the YAML-configuration." + } + } +} From bc9b9048f01d6c5845ddd97286ff9e801af91b69 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Tue, 11 Jul 2023 21:36:44 +0200 Subject: [PATCH 048/154] Add Reolink sensor platform (#96323) * Add Reolink sensor platform * fix styling * Add state class * Add Event connection sensor * Update homeassistant/components/reolink/sensor.py Co-authored-by: Joost Lekkerkerker * Use translation keys * fix json * fix json 2 * fix json 3 * Apply suggestions from code review Co-authored-by: G Johansson --------- Co-authored-by: Joost Lekkerkerker Co-authored-by: G Johansson --- .coveragerc | 1 + homeassistant/components/reolink/__init__.py | 1 + homeassistant/components/reolink/host.py | 9 ++ homeassistant/components/reolink/sensor.py | 121 ++++++++++++++++++ homeassistant/components/reolink/strings.json | 13 ++ 5 files changed, 145 insertions(+) create mode 100644 homeassistant/components/reolink/sensor.py diff --git a/.coveragerc b/.coveragerc index 2e10d1be2570c7..912c472de3e19b 100644 --- a/.coveragerc +++ b/.coveragerc @@ -991,6 +991,7 @@ omit = homeassistant/components/reolink/light.py homeassistant/components/reolink/number.py homeassistant/components/reolink/select.py + homeassistant/components/reolink/sensor.py homeassistant/components/reolink/siren.py homeassistant/components/reolink/switch.py homeassistant/components/reolink/update.py diff --git a/homeassistant/components/reolink/__init__.py b/homeassistant/components/reolink/__init__.py index 923df261d843fc..2de87659919d18 100644 --- a/homeassistant/components/reolink/__init__.py +++ b/homeassistant/components/reolink/__init__.py @@ -30,6 +30,7 @@ Platform.LIGHT, Platform.NUMBER, Platform.SELECT, + Platform.SENSOR, Platform.SIREN, Platform.SWITCH, Platform.UPDATE, diff --git a/homeassistant/components/reolink/host.py b/homeassistant/components/reolink/host.py index 81fbda63fef00c..dac02b913152b3 100644 --- a/homeassistant/components/reolink/host.py +++ b/homeassistant/components/reolink/host.py @@ -432,6 +432,15 @@ def unregister_webhook(self): webhook.async_unregister(self._hass, self.webhook_id) self.webhook_id = None + @property + def event_connection(self) -> str: + """Return the event connection type.""" + if self._webhook_reachable: + return "onvif_push" + if self._long_poll_received: + return "onvif_long_poll" + return "fast_poll" + async def _async_long_polling(self, *_) -> None: """Use ONVIF long polling to immediately receive events.""" # This task will be cancelled once _async_stop_long_polling is called diff --git a/homeassistant/components/reolink/sensor.py b/homeassistant/components/reolink/sensor.py new file mode 100644 index 00000000000000..42758dc99290ca --- /dev/null +++ b/homeassistant/components/reolink/sensor.py @@ -0,0 +1,121 @@ +"""Component providing support for Reolink sensors.""" +from __future__ import annotations + +from collections.abc import Callable +from dataclasses import dataclass +from datetime import date, datetime +from decimal import Decimal + +from reolink_aio.api import Host + +from homeassistant.components.sensor import ( + SensorDeviceClass, + SensorEntity, + SensorEntityDescription, + SensorStateClass, +) +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import EntityCategory +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.typing import StateType + +from . import ReolinkData +from .const import DOMAIN +from .entity import ReolinkHostCoordinatorEntity + + +@dataclass +class ReolinkHostSensorEntityDescriptionMixin: + """Mixin values for Reolink host sensor entities.""" + + value: Callable[[Host], bool] + + +@dataclass +class ReolinkHostSensorEntityDescription( + SensorEntityDescription, ReolinkHostSensorEntityDescriptionMixin +): + """A class that describes host sensor entities.""" + + supported: Callable[[Host], bool] = lambda host: True + + +HOST_SENSORS = ( + ReolinkHostSensorEntityDescription( + key="wifi_signal", + translation_key="wifi_signal", + icon="mdi:wifi", + state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, + entity_registry_enabled_default=False, + value=lambda api: api.wifi_signal, + supported=lambda api: api.supported(None, "wifi") and api.wifi_connection, + ), +) + + +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up a Reolink IP Camera.""" + reolink_data: ReolinkData = hass.data[DOMAIN][config_entry.entry_id] + + entities: list[ReolinkHostSensorEntity | EventConnectionSensorEntity] = [ + ReolinkHostSensorEntity(reolink_data, entity_description) + for entity_description in HOST_SENSORS + if entity_description.supported(reolink_data.host.api) + ] + entities.append(EventConnectionSensorEntity(reolink_data)) + async_add_entities(entities) + + +class ReolinkHostSensorEntity(ReolinkHostCoordinatorEntity, SensorEntity): + """Base sensor class for Reolink host sensors.""" + + entity_description: ReolinkHostSensorEntityDescription + + def __init__( + self, + reolink_data: ReolinkData, + entity_description: ReolinkHostSensorEntityDescription, + ) -> None: + """Initialize Reolink binary sensor.""" + super().__init__(reolink_data) + self.entity_description = entity_description + + self._attr_unique_id = f"{self._host.unique_id}_{entity_description.key}" + + @property + def native_value(self) -> StateType | date | datetime | Decimal: + """Return the value reported by the sensor.""" + return self.entity_description.value(self._host.api) + + +class EventConnectionSensorEntity(ReolinkHostCoordinatorEntity, SensorEntity): + """Reolink Event connection sensor.""" + + def __init__( + self, + reolink_data: ReolinkData, + ) -> None: + """Initialize Reolink binary sensor.""" + super().__init__(reolink_data) + self.entity_description = SensorEntityDescription( + key="event_connection", + translation_key="event_connection", + icon="mdi:swap-horizontal", + device_class=SensorDeviceClass.ENUM, + entity_category=EntityCategory.DIAGNOSTIC, + entity_registry_enabled_default=False, + options=["onvif_push", "onvif_long_poll", "fast_poll"], + ) + + self._attr_unique_id = f"{self._host.unique_id}_{self.entity_description.key}" + + @property + def native_value(self) -> str: + """Return the value reported by the sensor.""" + return self._host.event_connection diff --git a/homeassistant/components/reolink/strings.json b/homeassistant/components/reolink/strings.json index 53f2e57b97bac5..c0c2094eeb9d10 100644 --- a/homeassistant/components/reolink/strings.json +++ b/homeassistant/components/reolink/strings.json @@ -93,6 +93,19 @@ "alwaysonatnight": "Auto & always on at night" } } + }, + "sensor": { + "event_connection": { + "name": "Event connection", + "state": { + "onvif_push": "ONVIF push", + "onvif_long_poll": "ONVIF long poll", + "fast_poll": "Fast poll" + } + }, + "wifi_signal": { + "name": "Wi-Fi signal" + } } } } From 91273481a8d7b1cff86c72d9f428fb85e1e162a0 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 21:52:25 +0200 Subject: [PATCH 049/154] Migrate number services to support translations (#96343) --- homeassistant/components/number/services.yaml | 4 ---- homeassistant/components/number/strings.json | 12 ++++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/number/services.yaml b/homeassistant/components/number/services.yaml index 2014c4c5221da9..dcbb955d739873 100644 --- a/homeassistant/components/number/services.yaml +++ b/homeassistant/components/number/services.yaml @@ -1,15 +1,11 @@ # Describes the format for available Number entity services set_value: - name: Set - description: Set the value of a Number entity. target: entity: domain: number fields: value: - name: Value - description: The target value the entity should be set to. example: 42 selector: text: diff --git a/homeassistant/components/number/strings.json b/homeassistant/components/number/strings.json index 46db471305c315..e954a55b280edd 100644 --- a/homeassistant/components/number/strings.json +++ b/homeassistant/components/number/strings.json @@ -154,5 +154,17 @@ "wind_speed": { "name": "[%key:component::sensor::entity_component::wind_speed::name%]" } + }, + "services": { + "set_value": { + "name": "Set", + "description": "Sets the value of a number.", + "fields": { + "value": { + "name": "Value", + "description": "The target value to set." + } + } + } } } From 76e3272432ad58493d94ef27c3fc4a6a91670824 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 21:59:08 +0200 Subject: [PATCH 050/154] Migrate camera services to support translations (#96313) * Migrate camera services to support translations * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> * Update homeassistant/components/camera/strings.json Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/camera/services.yaml | 28 --------- homeassistant/components/camera/strings.json | 63 ++++++++++++++++++- 2 files changed, 62 insertions(+), 29 deletions(-) diff --git a/homeassistant/components/camera/services.yaml b/homeassistant/components/camera/services.yaml index 024bb927508900..55ac9f2bfeba03 100644 --- a/homeassistant/components/camera/services.yaml +++ b/homeassistant/components/camera/services.yaml @@ -1,65 +1,47 @@ # Describes the format for available camera services turn_off: - name: Turn off - description: Turn off camera. target: entity: domain: camera turn_on: - name: Turn on - description: Turn on camera. target: entity: domain: camera enable_motion_detection: - name: Enable motion detection - description: Enable the motion detection in a camera. target: entity: domain: camera disable_motion_detection: - name: Disable motion detection - description: Disable the motion detection in a camera. target: entity: domain: camera snapshot: - name: Take snapshot - description: Take a snapshot from a camera. target: entity: domain: camera fields: filename: - name: Filename - description: Template of a Filename. Variable is entity_id. required: true example: "/tmp/snapshot_{{ entity_id.name }}.jpg" selector: text: play_stream: - name: Play stream - description: Play camera stream on supported media player. target: entity: domain: camera fields: media_player: - name: Media Player - description: Name(s) of media player to stream to. required: true selector: entity: domain: media_player format: - name: Format - description: Stream format supported by media player. default: "hls" selector: select: @@ -67,22 +49,16 @@ play_stream: - "hls" record: - name: Record - description: Record live camera feed. target: entity: domain: camera fields: filename: - name: Filename - description: Template of a Filename. Variable is entity_id. Must be mp4. required: true example: "/tmp/snapshot_{{ entity_id.name }}.mp4" selector: text: duration: - name: Duration - description: Target recording length. default: 30 selector: number: @@ -90,10 +66,6 @@ record: max: 3600 unit_of_measurement: seconds lookback: - name: Lookback - description: - Target lookback period to include in addition to duration. Only - available if there is currently an active HLS stream. default: 0 selector: number: diff --git a/homeassistant/components/camera/strings.json b/homeassistant/components/camera/strings.json index 0722ec1c5e6dd2..ac061194d5cc49 100644 --- a/homeassistant/components/camera/strings.json +++ b/homeassistant/components/camera/strings.json @@ -34,5 +34,66 @@ } } } - } + }, + "services": { + "turn_off": { + "name": "Turn off", + "description": "Turns off the camera." + }, + "turn_on": { + "name": "Turn on", + "description": "Turns on the camera." + }, + "enable_motion_detection": { + "name": "Enable motion detection", + "description": "Enables the motion detection." + }, + "disable_motion_detection": { + "name": "Disable motion detection", + "description": "Disables the motion detection." + }, + "snapshot": { + "name": "Take snapshot", + "description": "Takes a snapshot from a camera.", + "fields": { + "filename": { + "name": "Filename", + "description": "Template of a filename. Variable available is `entity_id`." + } + } + }, + "play_stream": { + "name": "Play stream", + "description": "Plays the camera stream on a supported media player.", + "fields": { + "media_player": { + "name": "Media player", + "description": "Media players to stream to." + }, + "format": { + "name": "Format", + "description": "Stream format supported by the media player." + } + } + }, + "record": { + "name": "Record", + "description": "Creates a recording of a live camera feed.", + "fields": { + "filename": { + "name": "[%key:component::camera::services::snapshot::fields::filename::name%]", + "description": "Template of a filename. Variable available is `entity_id`. Must be mp4." + }, + "duration": { + "name": "Duration", + "description": "Planned duration of the recording. The actual duration may vary." + }, + "lookback": { + "name": "Lookback", + "description": "Planned lookback period to include in the recording (in addition to the duration). Only available if there is currently an active HLS stream. The actual length of the lookback period may vary." + } + } + } + }, + "selector": {} } From aea2fc68e78826fef534d73c017c2dc0e25621b7 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 22:00:00 +0200 Subject: [PATCH 051/154] Migrate backup services to support translations (#96308) * Migrate backup services to support translations * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/backup/services.yaml | 2 -- homeassistant/components/backup/strings.json | 8 ++++++++ 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 homeassistant/components/backup/strings.json diff --git a/homeassistant/components/backup/services.yaml b/homeassistant/components/backup/services.yaml index d001c57ef5caf3..900aa39dd6e404 100644 --- a/homeassistant/components/backup/services.yaml +++ b/homeassistant/components/backup/services.yaml @@ -1,3 +1 @@ create: - name: Create backup - description: Create a new backup. diff --git a/homeassistant/components/backup/strings.json b/homeassistant/components/backup/strings.json new file mode 100644 index 00000000000000..6ad3416b1b937d --- /dev/null +++ b/homeassistant/components/backup/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "create": { + "name": "Create backup", + "description": "Creates a new backup." + } + } +} From 0ff015c3adc3830ebca4b9d16a6d4ee440dc0467 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 23:04:27 +0200 Subject: [PATCH 052/154] Migrate integration services (A) to support translations (#96362) --- homeassistant/components/abode/services.yaml | 14 -- homeassistant/components/abode/strings.json | 36 +++++ .../components/adguard/services.yaml | 22 --- homeassistant/components/adguard/strings.json | 56 ++++++++ homeassistant/components/ads/services.yaml | 8 -- homeassistant/components/ads/strings.json | 22 +++ .../components/advantage_air/services.yaml | 4 - .../components/advantage_air/strings.json | 12 ++ .../components/aftership/services.yaml | 14 -- .../components/aftership/strings.json | 36 +++++ .../components/agent_dvr/services.yaml | 10 -- .../components/agent_dvr/strings.json | 22 +++ .../components/alarmdecoder/services.yaml | 8 -- .../components/alarmdecoder/strings.json | 26 +++- .../components/ambiclimate/services.yaml | 19 --- .../components/ambiclimate/strings.json | 40 ++++++ .../components/amcrest/services.yaml | 51 ------- homeassistant/components/amcrest/strings.json | 130 ++++++++++++++++++ .../components/androidtv/services.yaml | 18 --- .../components/androidtv/strings.json | 44 ++++++ 20 files changed, 423 insertions(+), 169 deletions(-) create mode 100644 homeassistant/components/ads/strings.json create mode 100644 homeassistant/components/aftership/strings.json create mode 100644 homeassistant/components/amcrest/strings.json diff --git a/homeassistant/components/abode/services.yaml b/homeassistant/components/abode/services.yaml index 843cc123c69b6f..f9d4e73a4e5c06 100644 --- a/homeassistant/components/abode/services.yaml +++ b/homeassistant/components/abode/services.yaml @@ -1,10 +1,6 @@ capture_image: - name: Capture image - description: Request a new image capture from a camera device. fields: entity_id: - name: Entity - description: Entity id of the camera to request an image. required: true selector: entity: @@ -12,31 +8,21 @@ capture_image: domain: camera change_setting: - name: Change setting - description: Change an Abode system setting. fields: setting: - name: Setting - description: Setting to change. required: true example: beeper_mute selector: text: value: - name: Value - description: Value of the setting. required: true example: "1" selector: text: trigger_automation: - name: Trigger automation - description: Trigger an Abode automation. fields: entity_id: - name: Entity - description: Entity id of the automation to trigger. required: true selector: entity: diff --git a/homeassistant/components/abode/strings.json b/homeassistant/components/abode/strings.json index b974007707e398..c0c32d487941b2 100644 --- a/homeassistant/components/abode/strings.json +++ b/homeassistant/components/abode/strings.json @@ -31,5 +31,41 @@ "single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]", "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" } + }, + "services": { + "capture_image": { + "name": "Capture image", + "description": "Request a new image capture from a camera device.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Entity id of the camera to request an image." + } + } + }, + "change_setting": { + "name": "Change setting", + "description": "Change an Abode system setting.", + "fields": { + "setting": { + "name": "Setting", + "description": "Setting to change." + }, + "value": { + "name": "Value", + "description": "Value of the setting." + } + } + }, + "trigger_automation": { + "name": "Trigger automation", + "description": "Trigger an Abode automation.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Entity id of the automation to trigger." + } + } + } } } diff --git a/homeassistant/components/adguard/services.yaml b/homeassistant/components/adguard/services.yaml index 5e4c2a157de443..f38dc4ed86693f 100644 --- a/homeassistant/components/adguard/services.yaml +++ b/homeassistant/components/adguard/services.yaml @@ -1,65 +1,43 @@ add_url: - name: Add url - description: Add a new filter subscription to AdGuard Home. fields: name: - name: Name - description: The name of the filter subscription. required: true example: Example selector: text: url: - name: Url - description: The filter URL to subscribe to, containing the filter rules. required: true example: https://www.example.com/filter/1.txt selector: text: remove_url: - name: Remove url - description: Removes a filter subscription from AdGuard Home. fields: url: - name: Url - description: The filter subscription URL to remove. required: true example: https://www.example.com/filter/1.txt selector: text: enable_url: - name: Enable url - description: Enables a filter subscription in AdGuard Home. fields: url: - name: Url - description: The filter subscription URL to enable. required: true example: https://www.example.com/filter/1.txt selector: text: disable_url: - name: Disable url - description: Disables a filter subscription in AdGuard Home. fields: url: - name: Url - description: The filter subscription URL to disable. required: true example: https://www.example.com/filter/1.txt selector: text: refresh: - name: Refresh - description: Refresh all filter subscriptions in AdGuard Home. fields: force: - name: Force - description: Force update (bypasses AdGuard Home throttling). "true" to force, or "false" to omit for a regular refresh. default: false selector: boolean: diff --git a/homeassistant/components/adguard/strings.json b/homeassistant/components/adguard/strings.json index bde73e82b37b37..95ce968a67f778 100644 --- a/homeassistant/components/adguard/strings.json +++ b/homeassistant/components/adguard/strings.json @@ -72,5 +72,61 @@ "name": "Query log" } } + }, + "services": { + "add_url": { + "name": "Add URL", + "description": "Add a new filter subscription to AdGuard Home.", + "fields": { + "name": { + "name": "Name", + "description": "The name of the filter subscription." + }, + "url": { + "name": "URL", + "description": "The filter URL to subscribe to, containing the filter rules." + } + } + }, + "remove_url": { + "name": "Remove URL", + "description": "Removes a filter subscription from AdGuard Home.", + "fields": { + "url": { + "name": "URL", + "description": "The filter subscription URL to remove." + } + } + }, + "enable_url": { + "name": "Enable URL", + "description": "Enables a filter subscription in AdGuard Home.", + "fields": { + "url": { + "name": "URL", + "description": "The filter subscription URL to enable." + } + } + }, + "disable_url": { + "name": "Disable URL", + "description": "Disables a filter subscription in AdGuard Home.", + "fields": { + "url": { + "name": "URL", + "description": "The filter subscription URL to disable." + } + } + }, + "refresh": { + "name": "Refresh", + "description": "Refresh all filter subscriptions in AdGuard Home.", + "fields": { + "force": { + "name": "Force", + "description": "Force update (bypasses AdGuard Home throttling). \"true\" to force, or \"false\" to omit for a regular refresh." + } + } + } } } diff --git a/homeassistant/components/ads/services.yaml b/homeassistant/components/ads/services.yaml index 53c514bb587067..e2d5c60ada2be1 100644 --- a/homeassistant/components/ads/services.yaml +++ b/homeassistant/components/ads/services.yaml @@ -1,19 +1,13 @@ # Describes the format for available ADS services write_data_by_name: - name: Write data by name - description: Write a value to the connected ADS device. fields: adsvar: - name: ADS variable - description: The name of the variable to write to. required: true example: ".global_var" selector: text: adstype: - name: ADS type - description: The data type of the variable to write to. required: true selector: select: @@ -25,8 +19,6 @@ write_data_by_name: - "udint" - "uint" value: - name: Value - description: The value to write to the variable. required: true selector: number: diff --git a/homeassistant/components/ads/strings.json b/homeassistant/components/ads/strings.json new file mode 100644 index 00000000000000..fd34973a21d7e2 --- /dev/null +++ b/homeassistant/components/ads/strings.json @@ -0,0 +1,22 @@ +{ + "services": { + "write_data_by_name": { + "name": "Write data by name", + "description": "Write a value to the connected ADS device.", + "fields": { + "adsvar": { + "name": "ADS variable", + "description": "The name of the variable to write to." + }, + "adstype": { + "name": "ADS type", + "description": "The data type of the variable to write to." + }, + "value": { + "name": "Value", + "description": "The value to write to the variable." + } + } + } + } +} diff --git a/homeassistant/components/advantage_air/services.yaml b/homeassistant/components/advantage_air/services.yaml index 6bd3bf815d6412..cb93ef568fc847 100644 --- a/homeassistant/components/advantage_air/services.yaml +++ b/homeassistant/components/advantage_air/services.yaml @@ -1,14 +1,10 @@ set_time_to: - name: Set Time To - description: Control timers to turn the system on or off after a set number of minutes target: entity: integration: advantage_air domain: sensor fields: minutes: - name: Minutes - description: Minutes until action required: true selector: number: diff --git a/homeassistant/components/advantage_air/strings.json b/homeassistant/components/advantage_air/strings.json index 76ecb174f6d2ae..39681201766a2f 100644 --- a/homeassistant/components/advantage_air/strings.json +++ b/homeassistant/components/advantage_air/strings.json @@ -16,5 +16,17 @@ "title": "Connect" } } + }, + "services": { + "set_time_to": { + "name": "Set time to", + "description": "Controls timers to turn the system on or off after a set number of minutes.", + "fields": { + "minutes": { + "name": "Minutes", + "description": "Minutes until action." + } + } + } } } diff --git a/homeassistant/components/aftership/services.yaml b/homeassistant/components/aftership/services.yaml index 62e339dbda89ad..2950d5162dd030 100644 --- a/homeassistant/components/aftership/services.yaml +++ b/homeassistant/components/aftership/services.yaml @@ -1,43 +1,29 @@ # Describes the format for available aftership services add_tracking: - name: Add tracking - description: Add new tracking number to Aftership. fields: tracking_number: - name: Tracking number - description: Tracking number for the new tracking required: true example: "123456789" selector: text: title: - name: Title - description: A custom title for the new tracking example: "Laptop" selector: text: slug: - name: Slug - description: Slug (carrier) of the new tracking example: "USPS" selector: text: remove_tracking: - name: Remove tracking - description: Remove a tracking number from Aftership. fields: tracking_number: - name: Tracking number - description: Tracking number of the tracking to remove required: true example: "123456789" selector: text: slug: - name: Slug - description: Slug (carrier) of the tracking to remove example: "USPS" selector: text: diff --git a/homeassistant/components/aftership/strings.json b/homeassistant/components/aftership/strings.json new file mode 100644 index 00000000000000..602138e82f58aa --- /dev/null +++ b/homeassistant/components/aftership/strings.json @@ -0,0 +1,36 @@ +{ + "services": { + "add_tracking": { + "name": "Add tracking", + "description": "Adds a new tracking number to Aftership.", + "fields": { + "tracking_number": { + "name": "Tracking number", + "description": "Tracking number for the new tracking." + }, + "title": { + "name": "Title", + "description": "A custom title for the new tracking." + }, + "slug": { + "name": "Slug", + "description": "Slug (carrier) of the new tracking." + } + } + }, + "remove_tracking": { + "name": "Remove tracking", + "description": "Removes a tracking number from Aftership.", + "fields": { + "tracking_number": { + "name": "Tracking number", + "description": "Tracking number of the tracking to remove." + }, + "slug": { + "name": "Slug", + "description": "Slug (carrier) of the tracking to remove." + } + } + } + } +} diff --git a/homeassistant/components/agent_dvr/services.yaml b/homeassistant/components/agent_dvr/services.yaml index 206b32cb526e9a..6256cfaac1ed36 100644 --- a/homeassistant/components/agent_dvr/services.yaml +++ b/homeassistant/components/agent_dvr/services.yaml @@ -1,38 +1,28 @@ start_recording: - name: Start recording - description: Enable continuous recording. target: entity: integration: agent_dvr domain: camera stop_recording: - name: Stop recording - description: Disable continuous recording. target: entity: integration: agent_dvr domain: camera enable_alerts: - name: Enable alerts - description: Enable alerts target: entity: integration: agent_dvr domain: camera disable_alerts: - name: Disable alerts - description: Disable alerts target: entity: integration: agent_dvr domain: camera snapshot: - name: Snapshot - description: Take a photo target: entity: integration: agent_dvr diff --git a/homeassistant/components/agent_dvr/strings.json b/homeassistant/components/agent_dvr/strings.json index 127fbb69b332e7..77167b8294bd65 100644 --- a/homeassistant/components/agent_dvr/strings.json +++ b/homeassistant/components/agent_dvr/strings.json @@ -16,5 +16,27 @@ "already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]" } + }, + "services": { + "start_recording": { + "name": "Start recording", + "description": "Enables continuous recording." + }, + "stop_recording": { + "name": "Stop recording", + "description": "Disables continuous recording." + }, + "enable_alerts": { + "name": "Enable alerts", + "description": "Enables alerts." + }, + "disable_alerts": { + "name": "Disable alerts", + "description": "Disables alerts." + }, + "snapshot": { + "name": "Snapshot", + "description": "Takes a photo." + } } } diff --git a/homeassistant/components/alarmdecoder/services.yaml b/homeassistant/components/alarmdecoder/services.yaml index 9d50eae07e68bd..91a6000e683bae 100644 --- a/homeassistant/components/alarmdecoder/services.yaml +++ b/homeassistant/components/alarmdecoder/services.yaml @@ -1,30 +1,22 @@ alarm_keypress: - name: Key press - description: Send custom keypresses to the alarm. target: entity: integration: alarmdecoder domain: alarm_control_panel fields: keypress: - name: Key press - description: "String to send to the alarm panel." required: true example: "*71" selector: text: alarm_toggle_chime: - name: Toggle Chime - description: Send the alarm the toggle chime command. target: entity: integration: alarmdecoder domain: alarm_control_panel fields: code: - name: Code - description: A code to toggle the alarm control panel chime with. required: true example: 1234 selector: diff --git a/homeassistant/components/alarmdecoder/strings.json b/homeassistant/components/alarmdecoder/strings.json index 33b3374904802a..585db4b1fa32e7 100644 --- a/homeassistant/components/alarmdecoder/strings.json +++ b/homeassistant/components/alarmdecoder/strings.json @@ -20,7 +20,9 @@ "error": { "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]" }, - "create_entry": { "default": "Successfully connected to AlarmDecoder." }, + "create_entry": { + "default": "Successfully connected to AlarmDecoder." + }, "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" } @@ -68,5 +70,27 @@ "loop_rfid": "RF Loop cannot be used without RF Serial.", "loop_range": "RF Loop must be an integer between 1 and 4." } + }, + "services": { + "alarm_keypress": { + "name": "Key press", + "description": "Sends custom keypresses to the alarm.", + "fields": { + "keypress": { + "name": "Key press", + "description": "String to send to the alarm panel." + } + } + }, + "alarm_toggle_chime": { + "name": "Toggle chime", + "description": "Sends the alarm the toggle chime command.", + "fields": { + "code": { + "name": "Code", + "description": "Code to toggle the alarm control panel chime with." + } + } + } } } diff --git a/homeassistant/components/ambiclimate/services.yaml b/homeassistant/components/ambiclimate/services.yaml index e5532ae82f9796..bf72d18b259fa6 100644 --- a/homeassistant/components/ambiclimate/services.yaml +++ b/homeassistant/components/ambiclimate/services.yaml @@ -1,53 +1,34 @@ # Describes the format for available services for ambiclimate set_comfort_mode: - name: Set comfort mode - description: > - Enable comfort mode on your AC. fields: name: - description: > - String with device name. required: true example: Bedroom selector: text: send_comfort_feedback: - name: Send comfort feedback - description: > - Send feedback for comfort mode. fields: name: - description: > - String with device name. required: true example: Bedroom selector: text: value: - description: > - Send any of the following comfort values: too_hot, too_warm, bit_warm, comfortable, bit_cold, too_cold, freezing required: true example: bit_warm selector: text: set_temperature_mode: - name: Set temperature mode - description: > - Enable temperature mode on your AC. fields: name: - description: > - String with device name. required: true example: Bedroom selector: text: value: - description: > - Target value in celsius required: true example: 22 selector: diff --git a/homeassistant/components/ambiclimate/strings.json b/homeassistant/components/ambiclimate/strings.json index c51c25a2f61cbe..2b55f7bebb60ad 100644 --- a/homeassistant/components/ambiclimate/strings.json +++ b/homeassistant/components/ambiclimate/strings.json @@ -18,5 +18,45 @@ "missing_configuration": "[%key:common::config_flow::abort::oauth2_missing_configuration%]", "access_token": "Unknown error generating an access token." } + }, + "services": { + "set_comfort_mode": { + "name": "Set comfort mode", + "description": "Enables comfort mode on your AC.", + "fields": { + "name": { + "name": "Device name", + "description": "String with device name." + } + } + }, + "send_comfort_feedback": { + "name": "Send comfort feedback", + "description": "Sends feedback for comfort mode.", + "fields": { + "name": { + "name": "[%key:component::ambiclimate::services::set_comfort_mode::fields::name::name%]", + "description": "[%key:component::ambiclimate::services::set_comfort_mode::fields::name::description%]" + }, + "value": { + "name": "Comfort value", + "description": "Send any of the following comfort values: too_hot, too_warm, bit_warm, comfortable, bit_cold, too_cold, freezing\n." + } + } + }, + "set_temperature_mode": { + "name": "Set temperature mode", + "description": "Enables temperature mode on your AC.", + "fields": { + "name": { + "name": "[%key:component::ambiclimate::services::set_comfort_mode::fields::name::name%]", + "description": "[%key:component::ambiclimate::services::set_comfort_mode::fields::name::description%]" + }, + "value": { + "name": "Temperature", + "description": "Target value in celsius." + } + } + } } } diff --git a/homeassistant/components/amcrest/services.yaml b/homeassistant/components/amcrest/services.yaml index b79a333101b2b7..cdcaf0e2c04c0a 100644 --- a/homeassistant/components/amcrest/services.yaml +++ b/homeassistant/components/amcrest/services.yaml @@ -1,82 +1,53 @@ enable_recording: - name: Enable recording - description: Enable continuous recording to camera storage. fields: entity_id: - name: Entity - description: "Name(s) of the cameras, or 'all' for all cameras." example: "camera.house_front" selector: text: disable_recording: - name: Disable recording - description: Disable continuous recording to camera storage. fields: entity_id: - name: Entity - description: "Name(s) of the cameras, or 'all' for all cameras." example: "camera.house_front" selector: text: enable_audio: - name: Enable audio - description: Enable audio stream. fields: entity_id: - name: Entity - description: "Name(s) of the cameras, or 'all' for all cameras." example: "camera.house_front" selector: text: disable_audio: - name: Disable audio - description: Disable audio stream. fields: entity_id: - name: Entity - description: "Name(s) of the cameras, or 'all' for all cameras." example: "camera.house_front" selector: text: enable_motion_recording: - name: Enable motion recording - description: Enable recording a clip to camera storage when motion is detected. fields: entity_id: - name: Entity - description: "Name(s) of the cameras, or 'all' for all cameras." example: "camera.house_front" selector: text: disable_motion_recording: - name: Disable motion recording - description: Disable recording a clip to camera storage when motion is detected. fields: entity_id: - name: Entity - description: "Name(s) of the cameras, or 'all' for all cameras." example: "camera.house_front" selector: text: goto_preset: - name: Go to preset - description: Move camera to PTZ preset. fields: entity_id: - description: "Name(s) of the cameras, or 'all' for all cameras." selector: entity: integration: amcrest domain: camera preset: - name: Preset - description: Preset number. required: true selector: number: @@ -84,18 +55,12 @@ goto_preset: max: 1000 set_color_bw: - name: Set color - description: Set camera color mode. fields: entity_id: - name: Entity - description: "Name(s) of the cameras, or 'all' for all cameras." example: "camera.house_front" selector: text: color_bw: - name: Color - description: Color mode. selector: select: options: @@ -104,40 +69,26 @@ set_color_bw: - "color" start_tour: - name: Start tour - description: Start camera's PTZ tour function. fields: entity_id: - name: Entity - description: "Name(s) of the cameras, or 'all' for all cameras." example: "camera.house_front" selector: text: stop_tour: - name: Stop tour - description: Stop camera's PTZ tour function. fields: entity_id: - name: Entity - description: "Name(s) of the cameras, or 'all' for all cameras." example: "camera.house_front" selector: text: ptz_control: - name: PTZ control - description: Move (Pan/Tilt) and/or Zoom a PTZ camera. fields: entity_id: - name: Entity - description: "Name of the camera, or 'all' for all cameras." example: "camera.house_front" selector: text: movement: - name: Movement - description: "Direction to move the camera." required: true selector: select: @@ -153,8 +104,6 @@ ptz_control: - "zoom_in" - "zoom_out" travel_time: - name: Travel time - description: "Travel time in fractional seconds: from 0 to 1." default: .2 selector: number: diff --git a/homeassistant/components/amcrest/strings.json b/homeassistant/components/amcrest/strings.json new file mode 100644 index 00000000000000..816511bf05e96a --- /dev/null +++ b/homeassistant/components/amcrest/strings.json @@ -0,0 +1,130 @@ +{ + "services": { + "enable_recording": { + "name": "Enable recording", + "description": "Enables continuous recording to camera storage.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name(s) of the cameras, or 'all' for all cameras." + } + } + }, + "disable_recording": { + "name": "Disable recording", + "description": "Disables continuous recording to camera storage.", + "fields": { + "entity_id": { + "name": "[%key:component::amcrest::services::enable_recording::fields::entity_id::name%]", + "description": "[%key:component::amcrest::services::enable_recording::fields::entity_id::description%]" + } + } + }, + "enable_audio": { + "name": "Enable audio", + "description": "Enables audio stream.", + "fields": { + "entity_id": { + "name": "[%key:component::amcrest::services::enable_recording::fields::entity_id::name%]", + "description": "[%key:component::amcrest::services::enable_recording::fields::entity_id::description%]" + } + } + }, + "disable_audio": { + "name": "Disable audio", + "description": "Disables audio stream.", + "fields": { + "entity_id": { + "name": "[%key:component::amcrest::services::enable_recording::fields::entity_id::name%]", + "description": "[%key:component::amcrest::services::enable_recording::fields::entity_id::description%]" + } + } + }, + "enable_motion_recording": { + "name": "Enables motion recording", + "description": "Enables recording a clip to camera storage when motion is detected.", + "fields": { + "entity_id": { + "name": "[%key:component::amcrest::services::enable_recording::fields::entity_id::name%]", + "description": "[%key:component::amcrest::services::enable_recording::fields::entity_id::description%]" + } + } + }, + "disable_motion_recording": { + "name": "Disables motion recording", + "description": "Disable recording a clip to camera storage when motion is detected.", + "fields": { + "entity_id": { + "name": "[%key:component::amcrest::services::enable_recording::fields::entity_id::name%]", + "description": "[%key:component::amcrest::services::enable_recording::fields::entity_id::description%]" + } + } + }, + "goto_preset": { + "name": "Go to preset", + "description": "Moves camera to PTZ preset.", + "fields": { + "entity_id": { + "name": "[%key:component::amcrest::services::enable_recording::fields::entity_id::name%]", + "description": "[%key:component::amcrest::services::enable_recording::fields::entity_id::description%]" + }, + "preset": { + "name": "Preset", + "description": "Preset number." + } + } + }, + "set_color_bw": { + "name": "Set color", + "description": "Sets camera color mode.", + "fields": { + "entity_id": { + "name": "[%key:component::amcrest::services::enable_recording::fields::entity_id::name%]", + "description": "[%key:component::amcrest::services::enable_recording::fields::entity_id::description%]" + }, + "color_bw": { + "name": "Color", + "description": "Color mode." + } + } + }, + "start_tour": { + "name": "Start tour", + "description": "Starts camera's PTZ tour function.", + "fields": { + "entity_id": { + "name": "[%key:component::amcrest::services::enable_recording::fields::entity_id::name%]", + "description": "[%key:component::amcrest::services::enable_recording::fields::entity_id::description%]" + } + } + }, + "stop_tour": { + "name": "Stop tour", + "description": "Stops camera's PTZ tour function.", + "fields": { + "entity_id": { + "name": "[%key:component::amcrest::services::enable_recording::fields::entity_id::name%]", + "description": "[%key:component::amcrest::services::enable_recording::fields::entity_id::description%]" + } + } + }, + "ptz_control": { + "name": "PTZ control", + "description": "Moves (pan/tilt) and/or zoom a PTZ camera.", + "fields": { + "entity_id": { + "name": "[%key:component::amcrest::services::enable_recording::fields::entity_id::name%]", + "description": "[%key:component::amcrest::services::enable_recording::fields::entity_id::description%]" + }, + "movement": { + "name": "Movement", + "description": "Direction to move the camera." + }, + "travel_time": { + "name": "Travel time", + "description": "Travel time in fractional seconds: from 0 to 1." + } + } + } + } +} diff --git a/homeassistant/components/androidtv/services.yaml b/homeassistant/components/androidtv/services.yaml index 4482f50f3e2672..41f7dbfea8f000 100644 --- a/homeassistant/components/androidtv/services.yaml +++ b/homeassistant/components/androidtv/services.yaml @@ -1,67 +1,49 @@ # Describes the format for available Android and Fire TV services adb_command: - name: ADB command - description: Send an ADB command to an Android / Fire TV device. target: entity: integration: androidtv domain: media_player fields: command: - name: Command - description: Either a key command or an ADB shell command. required: true example: "HOME" selector: text: download: - name: Download - description: Download a file from your Android / Fire TV device to your Home Assistant instance. target: entity: integration: androidtv domain: media_player fields: device_path: - name: Device path - description: The filepath on the Android / Fire TV device. required: true example: "/storage/emulated/0/Download/example.txt" selector: text: local_path: - name: Local path - description: The filepath on your Home Assistant instance. required: true example: "/config/www/example.txt" selector: text: upload: - name: Upload - description: Upload a file from your Home Assistant instance to an Android / Fire TV device. target: entity: integration: androidtv domain: media_player fields: device_path: - name: Device path - description: The filepath on the Android / Fire TV device. required: true example: "/storage/emulated/0/Download/example.txt" selector: text: local_path: - name: Local path - description: The filepath on your Home Assistant instance. required: true example: "/config/www/example.txt" selector: text: learn_sendevent: - name: Learn sendevent - description: Translate a key press on a remote into ADB 'sendevent' commands. You must press one button on the remote within 8 seconds of calling this service. target: entity: integration: androidtv diff --git a/homeassistant/components/androidtv/strings.json b/homeassistant/components/androidtv/strings.json index e7d06a9f6248b2..9eb3d14a2253b1 100644 --- a/homeassistant/components/androidtv/strings.json +++ b/homeassistant/components/androidtv/strings.json @@ -59,5 +59,49 @@ "error": { "invalid_det_rules": "Invalid state detection rules" } + }, + "services": { + "adb_command": { + "name": "ADB command", + "description": "Sends an ADB command to an Android / Fire TV device.", + "fields": { + "command": { + "name": "Command", + "description": "Either a key command or an ADB shell command." + } + } + }, + "download": { + "name": "Download", + "description": "Downloads a file from your Android / Fire TV device to your Home Assistant instance.", + "fields": { + "device_path": { + "name": "Device path", + "description": "The filepath on the Android / Fire TV device." + }, + "local_path": { + "name": "Local path", + "description": "The filepath on your Home Assistant instance." + } + } + }, + "upload": { + "name": "Upload", + "description": "Uploads a file from your Home Assistant instance to an Android / Fire TV device.", + "fields": { + "device_path": { + "name": "Device path", + "description": "The filepath on the Android / Fire TV device." + }, + "local_path": { + "name": "Local path", + "description": "The filepath on your Home Assistant instance." + } + } + }, + "learn_sendevent": { + "name": "Learn sendevent", + "description": "Translates a key press on a remote into ADB 'sendevent' commands. You must press one button on the remote within 8 seconds of calling this service." + } } } From c252758ac2dc825972b65f0951d28a3e06a44d92 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 23:06:32 +0200 Subject: [PATCH 053/154] Migrate integration services (B-D) to support translations (#96363) --- homeassistant/components/alert/services.yaml | 6 -- homeassistant/components/alert/strings.json | 14 ++++ .../components/blackbird/services.yaml | 6 -- .../components/blackbird/strings.json | 18 +++++ homeassistant/components/blink/services.yaml | 21 ------ homeassistant/components/blink/strings.json | 52 +++++++++++++- .../components/bluesound/services.yaml | 18 ----- .../components/bluesound/strings.json | 48 +++++++++++++ .../bluetooth_tracker/services.yaml | 2 - .../components/bluetooth_tracker/strings.json | 8 +++ homeassistant/components/bond/services.yaml | 30 -------- homeassistant/components/bond/strings.json | 70 +++++++++++++++++++ .../components/browser/services.yaml | 4 -- homeassistant/components/browser/strings.json | 14 ++++ homeassistant/components/cast/services.yaml | 8 --- homeassistant/components/cast/strings.json | 22 +++++- .../components/channels/services.yaml | 8 --- .../components/channels/strings.json | 22 ++++++ .../components/cloudflare/services.yaml | 2 - .../components/cloudflare/strings.json | 6 ++ .../components/color_extractor/services.yaml | 12 ---- .../components/color_extractor/strings.json | 18 +++++ .../components/command_line/services.yaml | 2 - .../components/command_line/strings.json | 6 ++ .../components/counter/services.yaml | 10 --- homeassistant/components/counter/strings.json | 24 +++++++ .../components/debugpy/services.yaml | 2 - homeassistant/components/debugpy/strings.json | 8 +++ homeassistant/components/deconz/services.yaml | 32 --------- homeassistant/components/deconz/strings.json | 44 ++++++++++++ .../components/denonavr/services.yaml | 9 --- .../components/denonavr/strings.json | 26 +++++++ .../components/dominos/services.yaml | 4 -- homeassistant/components/dominos/strings.json | 14 ++++ .../components/downloader/services.yaml | 10 --- .../components/downloader/strings.json | 26 +++++++ .../components/duckdns/services.yaml | 4 -- homeassistant/components/duckdns/strings.json | 14 ++++ .../components/dynalite/services.yaml | 13 ---- .../components/dynalite/strings.json | 38 ++++++++++ 40 files changed, 490 insertions(+), 205 deletions(-) create mode 100644 homeassistant/components/blackbird/strings.json create mode 100644 homeassistant/components/bluesound/strings.json create mode 100644 homeassistant/components/bluetooth_tracker/strings.json create mode 100644 homeassistant/components/browser/strings.json create mode 100644 homeassistant/components/channels/strings.json create mode 100644 homeassistant/components/color_extractor/strings.json create mode 100644 homeassistant/components/debugpy/strings.json create mode 100644 homeassistant/components/dominos/strings.json create mode 100644 homeassistant/components/downloader/strings.json create mode 100644 homeassistant/components/duckdns/strings.json diff --git a/homeassistant/components/alert/services.yaml b/homeassistant/components/alert/services.yaml index 3242a9cedb4f02..e1d842f5bc4026 100644 --- a/homeassistant/components/alert/services.yaml +++ b/homeassistant/components/alert/services.yaml @@ -1,20 +1,14 @@ toggle: - name: Toggle - description: Toggle alert's notifications. target: entity: domain: alert turn_off: - name: Turn off - description: Silence alert's notifications. target: entity: domain: alert turn_on: - name: Turn on - description: Reset alert's notifications. target: entity: domain: alert diff --git a/homeassistant/components/alert/strings.json b/homeassistant/components/alert/strings.json index 4d948b2f4d11b1..16192d5d59561d 100644 --- a/homeassistant/components/alert/strings.json +++ b/homeassistant/components/alert/strings.json @@ -9,5 +9,19 @@ "on": "[%key:common::state::active%]" } } + }, + "services": { + "toggle": { + "name": "Toggle", + "description": "Toggles alert's notifications." + }, + "turn_off": { + "name": "Turn off", + "description": "Silences alert's notifications." + }, + "turn_on": { + "name": "Turn on", + "description": "Resets alert's notifications." + } } } diff --git a/homeassistant/components/blackbird/services.yaml b/homeassistant/components/blackbird/services.yaml index 7b3096c25e4f61..00425c93eb6001 100644 --- a/homeassistant/components/blackbird/services.yaml +++ b/homeassistant/components/blackbird/services.yaml @@ -1,10 +1,6 @@ set_all_zones: - name: Set all zones - description: Set all Blackbird zones to a single source. fields: entity_id: - name: Entity - description: Name of any blackbird zone. required: true example: "media_player.zone_1" selector: @@ -12,8 +8,6 @@ set_all_zones: integration: blackbird domain: media_player source: - name: Source - description: Name of source to switch to. required: true example: "Source 1" selector: diff --git a/homeassistant/components/blackbird/strings.json b/homeassistant/components/blackbird/strings.json new file mode 100644 index 00000000000000..93c0e6ef23dbc4 --- /dev/null +++ b/homeassistant/components/blackbird/strings.json @@ -0,0 +1,18 @@ +{ + "services": { + "set_all_zones": { + "name": "Set all zones", + "description": "Sets all Blackbird zones to a single source.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name of any blackbird zone." + }, + "source": { + "name": "Source", + "description": "Name of source to switch to." + } + } + } + } +} diff --git a/homeassistant/components/blink/services.yaml b/homeassistant/components/blink/services.yaml index 3d51ba2f7bbe56..95f4d33f91f732 100644 --- a/homeassistant/components/blink/services.yaml +++ b/homeassistant/components/blink/services.yaml @@ -1,62 +1,41 @@ # Describes the format for available Blink services blink_update: - name: Update - description: Force a refresh. - trigger_camera: - name: Trigger camera - description: Request camera to take new image. target: entity: integration: blink domain: camera save_video: - name: Save video - description: Save last recorded video clip to local file. fields: name: - name: Name - description: Name of camera to grab video from. required: true example: "Living Room" selector: text: filename: - name: File name - description: Filename to writable path (directory may need to be included in allowlist_external_dirs in config) required: true example: "/tmp/video.mp4" selector: text: save_recent_clips: - name: Save recent clips - description: 'Save all recent video clips to local directory with file pattern "%Y%m%d_%H%M%S_{name}.mp4"' fields: name: - name: Name - description: Name of camera to grab recent clips from. required: true example: "Living Room" selector: text: file_path: - name: Output directory - description: Directory name of writable path (directory may need to be included in allowlist_external_dirs in config) required: true example: "/tmp" selector: text: send_pin: - name: Send pin - description: Send a new PIN to blink for 2FA. fields: pin: - name: Pin - description: PIN received from blink. Leave empty if you only received a verification email. example: "abc123" selector: text: diff --git a/homeassistant/components/blink/strings.json b/homeassistant/components/blink/strings.json index 61c9a21af37043..6c07d1fea5513f 100644 --- a/homeassistant/components/blink/strings.json +++ b/homeassistant/components/blink/strings.json @@ -10,7 +10,9 @@ }, "2fa": { "title": "Two-factor authentication", - "data": { "2fa": "Two-factor code" }, + "data": { + "2fa": "Two-factor code" + }, "description": "Enter the PIN sent via email or SMS" } }, @@ -46,5 +48,53 @@ "name": "Camera armed" } } + }, + "services": { + "blink_update": { + "name": "Update", + "description": "Forces a refresh." + }, + "trigger_camera": { + "name": "Trigger camera", + "description": "Requests camera to take new image." + }, + "save_video": { + "name": "Save video", + "description": "Saves last recorded video clip to local file.", + "fields": { + "name": { + "name": "Name", + "description": "Name of camera to grab video from." + }, + "filename": { + "name": "File name", + "description": "Filename to writable path (directory may need to be included in allowlist_external_dirs in config)." + } + } + }, + "save_recent_clips": { + "name": "Save recent clips", + "description": "Saves all recent video clips to local directory with file pattern \"%Y%m%d_%H%M%S_{name}.mp4\".", + "fields": { + "name": { + "name": "Name", + "description": "Name of camera to grab recent clips from." + }, + "file_path": { + "name": "Output directory", + "description": "Directory name of writable path (directory may need to be included in allowlist_external_dirs in config)." + } + } + }, + "send_pin": { + "name": "Send pin", + "description": "Sends a new PIN to blink for 2FA.", + "fields": { + "pin": { + "name": "Pin", + "description": "PIN received from blink. Leave empty if you only received a verification email." + } + } + } } } diff --git a/homeassistant/components/bluesound/services.yaml b/homeassistant/components/bluesound/services.yaml index 7c04cc00f39851..7ab69a82124211 100644 --- a/homeassistant/components/bluesound/services.yaml +++ b/homeassistant/components/bluesound/services.yaml @@ -1,54 +1,36 @@ join: - name: Join - description: Group player together. fields: master: - name: Master - description: Entity ID of the player that should become the master of the group. required: true selector: entity: integration: bluesound domain: media_player entity_id: - name: Entity - description: Name of entity that will coordinate the grouping. Platform dependent. selector: entity: integration: bluesound domain: media_player unjoin: - name: Unjoin - description: Unjoin the player from a group. fields: entity_id: - name: Entity - description: Name of entity that will be unjoined from their group. Platform dependent. selector: entity: integration: bluesound domain: media_player set_sleep_timer: - name: Set sleep timer - description: "Set a Bluesound timer. It will increase timer in steps: 15, 30, 45, 60, 90, 0" fields: entity_id: - name: Entity - description: Name(s) of entities that will have a timer set. selector: entity: integration: bluesound domain: media_player clear_sleep_timer: - name: Clear sleep timer - description: Clear a Bluesound timer. fields: entity_id: - name: Entity - description: Name(s) of entities that will have the timer cleared. selector: entity: integration: bluesound diff --git a/homeassistant/components/bluesound/strings.json b/homeassistant/components/bluesound/strings.json new file mode 100644 index 00000000000000..f41c34a7449ac2 --- /dev/null +++ b/homeassistant/components/bluesound/strings.json @@ -0,0 +1,48 @@ +{ + "services": { + "join": { + "name": "Join", + "description": "Group player together.", + "fields": { + "master": { + "name": "Master", + "description": "Entity ID of the player that should become the master of the group." + }, + "entity_id": { + "name": "Entity", + "description": "Name of entity that will coordinate the grouping. Platform dependent." + } + } + }, + "unjoin": { + "name": "Unjoin", + "description": "Unjoin the player from a group.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name of entity that will be unjoined from their group. Platform dependent." + } + } + }, + "set_sleep_timer": { + "name": "Set sleep timer", + "description": "Set a Bluesound timer. It will increase timer in steps: 15, 30, 45, 60, 90, 0.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name(s) of entities that will have a timer set." + } + } + }, + "clear_sleep_timer": { + "name": "Clear sleep timer", + "description": "Clear a Bluesound timer.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name(s) of entities that will have the timer cleared." + } + } + } + } +} diff --git a/homeassistant/components/bluetooth_tracker/services.yaml b/homeassistant/components/bluetooth_tracker/services.yaml index 3150403dbf1057..91b8669505b380 100644 --- a/homeassistant/components/bluetooth_tracker/services.yaml +++ b/homeassistant/components/bluetooth_tracker/services.yaml @@ -1,3 +1 @@ update: - name: Update - description: Trigger manual tracker update diff --git a/homeassistant/components/bluetooth_tracker/strings.json b/homeassistant/components/bluetooth_tracker/strings.json new file mode 100644 index 00000000000000..bf22845d054ab5 --- /dev/null +++ b/homeassistant/components/bluetooth_tracker/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "update": { + "name": "Update", + "description": "Triggers manual tracker update." + } + } +} diff --git a/homeassistant/components/bond/services.yaml b/homeassistant/components/bond/services.yaml index 6be18eaa1ef5e9..bda0bc5835f23c 100644 --- a/homeassistant/components/bond/services.yaml +++ b/homeassistant/components/bond/services.yaml @@ -1,13 +1,9 @@ # Describes the format for available bond services set_fan_speed_tracked_state: - name: Set fan speed tracked state - description: Sets the tracked fan speed for a bond fan fields: entity_id: - description: Name(s) of entities to set the tracked fan speed. example: "fan.living_room_fan" - name: Entity required: true selector: entity: @@ -15,8 +11,6 @@ set_fan_speed_tracked_state: domain: fan speed: required: true - name: Fan Speed - description: Fan Speed as %. example: 50 selector: number: @@ -26,13 +20,9 @@ set_fan_speed_tracked_state: mode: slider set_switch_power_tracked_state: - name: Set switch power tracked state - description: Sets the tracked power state of a bond switch fields: entity_id: - description: Name(s) of entities to set the tracked power state of. example: "switch.whatever" - name: Entity required: true selector: entity: @@ -40,20 +30,14 @@ set_switch_power_tracked_state: domain: switch power_state: required: true - name: Power state - description: Power state example: true selector: boolean: set_light_power_tracked_state: - name: Set light power tracked state - description: Sets the tracked power state of a bond light fields: entity_id: - description: Name(s) of entities to set the tracked power state of. example: "light.living_room_lights" - name: Entity required: true selector: entity: @@ -61,20 +45,14 @@ set_light_power_tracked_state: domain: light power_state: required: true - name: Power state - description: Power state example: true selector: boolean: set_light_brightness_tracked_state: - name: Set light brightness tracked state - description: Sets the tracked brightness state of a bond light fields: entity_id: - description: Name(s) of entities to set the tracked brightness state of. example: "light.living_room_lights" - name: Entity required: true selector: entity: @@ -82,8 +60,6 @@ set_light_brightness_tracked_state: domain: light brightness: required: true - name: Brightness - description: Brightness example: 50 selector: number: @@ -93,24 +69,18 @@ set_light_brightness_tracked_state: mode: slider start_increasing_brightness: - name: Start increasing brightness - description: "Start increasing the brightness of the light. (deprecated)" target: entity: integration: bond domain: light start_decreasing_brightness: - name: Start decreasing brightness - description: "Start decreasing the brightness of the light. (deprecated)" target: entity: integration: bond domain: light stop: - name: Stop - description: "Stop any in-progress action and empty the queue. (deprecated)" target: entity: integration: bond diff --git a/homeassistant/components/bond/strings.json b/homeassistant/components/bond/strings.json index e923ded939e301..9cbd895683c563 100644 --- a/homeassistant/components/bond/strings.json +++ b/homeassistant/components/bond/strings.json @@ -24,5 +24,75 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" } + }, + "services": { + "set_fan_speed_tracked_state": { + "name": "Set fan speed tracked state", + "description": "Sets the tracked fan speed for a bond fan.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name(s) of entities to set the tracked fan speed." + }, + "speed": { + "name": "Fan Speed", + "description": "Fan Speed as %." + } + } + }, + "set_switch_power_tracked_state": { + "name": "Set switch power tracked state", + "description": "Sets the tracked power state of a bond switch.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name(s) of entities to set the tracked power state of." + }, + "power_state": { + "name": "Power state", + "description": "Power state." + } + } + }, + "set_light_power_tracked_state": { + "name": "Set light power tracked state", + "description": "Sets the tracked power state of a bond light.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name(s) of entities to set the tracked power state of." + }, + "power_state": { + "name": "Power state", + "description": "Power state." + } + } + }, + "set_light_brightness_tracked_state": { + "name": "Set light brightness tracked state", + "description": "Sets the tracked brightness state of a bond light.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name(s) of entities to set the tracked brightness state of." + }, + "brightness": { + "name": "Brightness", + "description": "Brightness." + } + } + }, + "start_increasing_brightness": { + "name": "Start increasing brightness", + "description": "Start increasing the brightness of the light. (deprecated)." + }, + "start_decreasing_brightness": { + "name": "Start decreasing brightness", + "description": "Start decreasing the brightness of the light. (deprecated)." + }, + "stop": { + "name": "Stop", + "description": "Stop any in-progress action and empty the queue. (deprecated)." + } } } diff --git a/homeassistant/components/browser/services.yaml b/homeassistant/components/browser/services.yaml index dd3ddd095cc45c..c2192911eeabda 100644 --- a/homeassistant/components/browser/services.yaml +++ b/homeassistant/components/browser/services.yaml @@ -1,10 +1,6 @@ browse_url: - name: Browse - description: Open a URL in the default browser on the host machine of Home Assistant. fields: url: - name: URL - description: The URL to open. required: true example: "https://www.home-assistant.io" selector: diff --git a/homeassistant/components/browser/strings.json b/homeassistant/components/browser/strings.json new file mode 100644 index 00000000000000..fafd5fb96b006f --- /dev/null +++ b/homeassistant/components/browser/strings.json @@ -0,0 +1,14 @@ +{ + "services": { + "browse_url": { + "name": "Browse", + "description": "Opens a URL in the default browser on the host machine of Home Assistant.", + "fields": { + "url": { + "name": "URL", + "description": "The URL to open." + } + } + } + } +} diff --git a/homeassistant/components/cast/services.yaml b/homeassistant/components/cast/services.yaml index f0fbcf4a8d757b..e2e23ad40a2dd6 100644 --- a/homeassistant/components/cast/services.yaml +++ b/homeassistant/components/cast/services.yaml @@ -1,25 +1,17 @@ show_lovelace_view: - name: Show lovelace view - description: Show a Lovelace view on a Chromecast. fields: entity_id: - name: Entity - description: Media Player entity to show the Lovelace view on. required: true selector: entity: integration: cast domain: media_player dashboard_path: - name: Dashboard path - description: The URL path of the Lovelace dashboard to show. required: true example: lovelace-cast selector: text: view_path: - name: View Path - description: The path of the Lovelace view to show. example: downstairs selector: text: diff --git a/homeassistant/components/cast/strings.json b/homeassistant/components/cast/strings.json index 719465e98ca182..4de0f85851f307 100644 --- a/homeassistant/components/cast/strings.json +++ b/homeassistant/components/cast/strings.json @@ -30,7 +30,7 @@ }, "advanced_options": { "title": "Advanced Google Cast configuration", - "description": "Allowed UUIDs - A comma-separated list of UUIDs of Cast devices to add to Home Assistant. Use only if you don’t want to add all available cast devices.\nIgnore CEC - A comma-separated list of Chromecasts that should ignore CEC data for determining the active input. This will be passed to pychromecast.IGNORE_CEC.", + "description": "Allowed UUIDs - A comma-separated list of UUIDs of Cast devices to add to Home Assistant. Use only if you don\u2019t want to add all available cast devices.\nIgnore CEC - A comma-separated list of Chromecasts that should ignore CEC data for determining the active input. This will be passed to pychromecast.IGNORE_CEC.", "data": { "ignore_cec": "Ignore CEC", "uuid": "Allowed UUIDs" @@ -40,5 +40,25 @@ "error": { "invalid_known_hosts": "Known hosts must be a comma separated list of hosts." } + }, + "services": { + "show_lovelace_view": { + "name": "Show dashboard view", + "description": "Shows a dashboard view on a Chromecast device.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Media player entity to show the dashboard view on." + }, + "dashboard_path": { + "name": "Dashboard path", + "description": "The URL path of the dashboard to show." + }, + "view_path": { + "name": "View path", + "description": "The path of the dashboard view to show." + } + } + } } } diff --git a/homeassistant/components/channels/services.yaml b/homeassistant/components/channels/services.yaml index 5aa2f1ebda73d2..73ac6675ccf8d6 100644 --- a/homeassistant/components/channels/services.yaml +++ b/homeassistant/components/channels/services.yaml @@ -1,30 +1,22 @@ seek_forward: - name: Seek forward - description: Seek forward by a set number of seconds. target: entity: integration: channels domain: media_player seek_backward: - name: Seek backward - description: Seek backward by a set number of seconds. target: entity: integration: channels domain: media_player seek_by: - name: Seek by - description: Seek by an inputted number of seconds. target: entity: integration: channels domain: media_player fields: seconds: - name: Seconds - description: Number of seconds to seek by. Negative numbers seek backwards. required: true selector: number: diff --git a/homeassistant/components/channels/strings.json b/homeassistant/components/channels/strings.json new file mode 100644 index 00000000000000..0eceed8a8e0b6d --- /dev/null +++ b/homeassistant/components/channels/strings.json @@ -0,0 +1,22 @@ +{ + "services": { + "seek_forward": { + "name": "Seek forward", + "description": "Seeks forward by a set number of seconds." + }, + "seek_backward": { + "name": "Seek backward", + "description": "Seeks backward by a set number of seconds." + }, + "seek_by": { + "name": "Seek by", + "description": "Seeks by an inputted number of seconds.", + "fields": { + "seconds": { + "name": "Seconds", + "description": "Number of seconds to seek by. Negative numbers seek backwards." + } + } + } + } +} diff --git a/homeassistant/components/cloudflare/services.yaml b/homeassistant/components/cloudflare/services.yaml index f9465e788d89e1..e800a3a3eeebb7 100644 --- a/homeassistant/components/cloudflare/services.yaml +++ b/homeassistant/components/cloudflare/services.yaml @@ -1,3 +1 @@ update_records: - name: Update records - description: Manually trigger update to Cloudflare records diff --git a/homeassistant/components/cloudflare/strings.json b/homeassistant/components/cloudflare/strings.json index 89bc67feeed0f7..080be414b5caad 100644 --- a/homeassistant/components/cloudflare/strings.json +++ b/homeassistant/components/cloudflare/strings.json @@ -38,5 +38,11 @@ "single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]", "unknown": "[%key:common::config_flow::error::unknown%]" } + }, + "services": { + "update_records": { + "name": "Update records", + "description": "Manually trigger update to Cloudflare records." + } } } diff --git a/homeassistant/components/color_extractor/services.yaml b/homeassistant/components/color_extractor/services.yaml index be278a59059427..2fd0b0db8152bd 100644 --- a/homeassistant/components/color_extractor/services.yaml +++ b/homeassistant/components/color_extractor/services.yaml @@ -1,25 +1,13 @@ turn_on: - name: Turn on - description: - Set the light RGB to the predominant color found in the image provided by - URL or file path. target: entity: domain: light fields: color_extract_url: - name: URL - description: - The URL of the image we want to extract RGB values from. Must be allowed - in allowlist_external_urls. example: https://www.example.com/images/logo.png selector: text: color_extract_path: - name: Path - description: - The full system path to the image we want to extract RGB values from. - Must be allowed in allowlist_external_dirs. example: /opt/images/logo.png selector: text: diff --git a/homeassistant/components/color_extractor/strings.json b/homeassistant/components/color_extractor/strings.json new file mode 100644 index 00000000000000..df720586631552 --- /dev/null +++ b/homeassistant/components/color_extractor/strings.json @@ -0,0 +1,18 @@ +{ + "services": { + "turn_on": { + "name": "Turn on", + "description": "Sets the light RGB to the predominant color found in the image provided by URL or file path.", + "fields": { + "color_extract_url": { + "name": "URL", + "description": "The URL of the image we want to extract RGB values from. Must be allowed in allowlist_external_urls." + }, + "color_extract_path": { + "name": "Path", + "description": "The full system path to the image we want to extract RGB values from. Must be allowed in allowlist_external_dirs." + } + } + } + } +} diff --git a/homeassistant/components/command_line/services.yaml b/homeassistant/components/command_line/services.yaml index f4cec426860635..c983a105c93977 100644 --- a/homeassistant/components/command_line/services.yaml +++ b/homeassistant/components/command_line/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload all command_line entities diff --git a/homeassistant/components/command_line/strings.json b/homeassistant/components/command_line/strings.json index dab4a77a6ec37d..e249ad877d56e1 100644 --- a/homeassistant/components/command_line/strings.json +++ b/homeassistant/components/command_line/strings.json @@ -4,5 +4,11 @@ "title": "Command Line YAML configuration has moved", "description": "Configuring Command Line `{platform}` using YAML has moved.\n\nConsult the documentation to move your YAML configuration to integration key and restart Home Assistant to fix this issue." } + }, + "services": { + "reload": { + "name": "Reload", + "description": "Reloads command line configuration from the YAML-configuration." + } } } diff --git a/homeassistant/components/counter/services.yaml b/homeassistant/components/counter/services.yaml index 835d39c9d2e038..643fc2230831bb 100644 --- a/homeassistant/components/counter/services.yaml +++ b/homeassistant/components/counter/services.yaml @@ -1,37 +1,27 @@ # Describes the format for available counter services decrement: - name: Decrement - description: Decrement a counter. target: entity: domain: counter increment: - name: Increment - description: Increment a counter. target: entity: domain: counter reset: - name: Reset - description: Reset a counter. target: entity: domain: counter set_value: - name: Set - description: Set the counter value target: entity: domain: counter fields: value: - name: Value required: true - description: The new counter value the entity should be set to. selector: number: min: 0 diff --git a/homeassistant/components/counter/strings.json b/homeassistant/components/counter/strings.json index 6dcfe14a03a241..0446b2447872e0 100644 --- a/homeassistant/components/counter/strings.json +++ b/homeassistant/components/counter/strings.json @@ -38,5 +38,29 @@ } } } + }, + "services": { + "decrement": { + "name": "Decrement", + "description": "Decrements a counter." + }, + "increment": { + "name": "Increment", + "description": "Increments a counter." + }, + "reset": { + "name": "Reset", + "description": "Resets a counter." + }, + "set_value": { + "name": "Set", + "description": "Sets the counter value.", + "fields": { + "value": { + "name": "Value", + "description": "The new counter value the entity should be set to." + } + } + } } } diff --git a/homeassistant/components/debugpy/services.yaml b/homeassistant/components/debugpy/services.yaml index c864684226f053..453b3af46bdd0a 100644 --- a/homeassistant/components/debugpy/services.yaml +++ b/homeassistant/components/debugpy/services.yaml @@ -1,4 +1,2 @@ # Describes the format for available Remote Python Debugger services start: - name: Start - description: Start the Remote Python Debugger diff --git a/homeassistant/components/debugpy/strings.json b/homeassistant/components/debugpy/strings.json new file mode 100644 index 00000000000000..b03a57a51dcf20 --- /dev/null +++ b/homeassistant/components/debugpy/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "start": { + "name": "Start", + "description": "Starts the Remote Python Debugger." + } + } +} diff --git a/homeassistant/components/deconz/services.yaml b/homeassistant/components/deconz/services.yaml index 9084728a216f63..d08312852b385c 100644 --- a/homeassistant/components/deconz/services.yaml +++ b/homeassistant/components/deconz/services.yaml @@ -1,65 +1,33 @@ configure: - name: Configure - description: >- - Configure attributes of either a device endpoint in deCONZ - or the deCONZ service itself. fields: entity: - name: Entity - description: Represents a specific device endpoint in deCONZ. selector: entity: integration: deconz field: - name: Path - description: >- - String representing a full path to deCONZ endpoint (when - entity is not specified) or a subpath of the device path for the - entity (when entity is specified). example: '"/lights/1/state" or "/state"' selector: text: data: - name: Configuration payload - description: JSON object with what data you want to alter. required: true example: '{"on": true}' selector: object: bridgeid: - name: Bridge identifier - description: >- - Unique string for each deCONZ hardware. - It can be found as part of the integration name. - Useful if you run multiple deCONZ integrations. example: "00212EFFFF012345" selector: text: device_refresh: - name: Device refresh - description: Refresh available devices from deCONZ. fields: bridgeid: - name: Bridge identifier - description: >- - Unique string for each deCONZ hardware. - It can be found as part of the integration name. - Useful if you run multiple deCONZ integrations. example: "00212EFFFF012345" selector: text: remove_orphaned_entries: - name: Remove orphaned entries - description: Clean up device and entity registry entries orphaned by deCONZ. fields: bridgeid: - name: Bridge identifier - description: >- - Unique string for each deCONZ hardware. - It can be found as part of the integration name. - Useful if you run multiple deCONZ integrations. example: "00212EFFFF012345" selector: text: diff --git a/homeassistant/components/deconz/strings.json b/homeassistant/components/deconz/strings.json index 45a19b0466da7f..448a221b2ca58e 100644 --- a/homeassistant/components/deconz/strings.json +++ b/homeassistant/components/deconz/strings.json @@ -105,5 +105,49 @@ "side_5": "Side 5", "side_6": "Side 6" } + }, + "services": { + "configure": { + "name": "Configure", + "description": "Configures attributes of either a device endpoint in deCONZ or the deCONZ service itself.", + "fields": { + "entity": { + "name": "Entity", + "description": "Represents a specific device endpoint in deCONZ." + }, + "field": { + "name": "Path", + "description": "String representing a full path to deCONZ endpoint (when entity is not specified) or a subpath of the device path for the entity (when entity is specified)." + }, + "data": { + "name": "Configuration payload", + "description": "JSON object with what data you want to alter." + }, + "bridgeid": { + "name": "Bridge identifier", + "description": "Unique string for each deCONZ hardware. It can be found as part of the integration name. Useful if you run multiple deCONZ integrations." + } + } + }, + "device_refresh": { + "name": "Device refresh", + "description": "Refreshes available devices from deCONZ.", + "fields": { + "bridgeid": { + "name": "Bridge identifier", + "description": "Unique string for each deCONZ hardware. It can be found as part of the integration name. Useful if you run multiple deCONZ integrations." + } + } + }, + "remove_orphaned_entries": { + "name": "Remove orphaned entries", + "description": "Cleans up device and entity registry entries orphaned by deCONZ.", + "fields": { + "bridgeid": { + "name": "Bridge identifier", + "description": "Unique string for each deCONZ hardware. It can be found as part of the integration name. Useful if you run multiple deCONZ integrations." + } + } + } } } diff --git a/homeassistant/components/denonavr/services.yaml b/homeassistant/components/denonavr/services.yaml index ee35732e3117e6..9c53ff9994a981 100644 --- a/homeassistant/components/denonavr/services.yaml +++ b/homeassistant/components/denonavr/services.yaml @@ -1,36 +1,27 @@ # Describes the format for available denonavr services get_command: - name: Get command - description: "Send a generic HTTP get command." target: entity: integration: denonavr domain: media_player fields: command: - name: Command - description: Endpoint of the command, including associated parameters. example: "/goform/formiPhoneAppDirect.xml?RCKSK0410370" required: true selector: text: set_dynamic_eq: - name: Set dynamic equalizer - description: "Enable or disable DynamicEQ." target: entity: integration: denonavr domain: media_player fields: dynamic_eq: - description: "True/false for enable/disable." default: true selector: boolean: update_audyssey: - name: Update audyssey - description: "Update Audyssey settings." target: entity: integration: denonavr diff --git a/homeassistant/components/denonavr/strings.json b/homeassistant/components/denonavr/strings.json index 1c85efc9ff4d29..a4e07e33a6a815 100644 --- a/homeassistant/components/denonavr/strings.json +++ b/homeassistant/components/denonavr/strings.json @@ -46,5 +46,31 @@ } } } + }, + "services": { + "get_command": { + "name": "Get command", + "description": "Send sa generic HTTP get command.", + "fields": { + "command": { + "name": "Command", + "description": "Endpoint of the command, including associated parameters." + } + } + }, + "set_dynamic_eq": { + "name": "Set dynamic equalizer", + "description": "Enables or disables DynamicEQ.", + "fields": { + "dynamic_eq": { + "name": "Dynamic equalizer", + "description": "True/false for enable/disable." + } + } + }, + "update_audyssey": { + "name": "Update Audyssey", + "description": "Updates Audyssey settings." + } } } diff --git a/homeassistant/components/dominos/services.yaml b/homeassistant/components/dominos/services.yaml index 6a354bc3a63a34..f2261072ddd182 100644 --- a/homeassistant/components/dominos/services.yaml +++ b/homeassistant/components/dominos/services.yaml @@ -1,10 +1,6 @@ order: - name: Order - description: Places a set of orders with Dominos Pizza. fields: order_entity_id: - name: Order Entity - description: The ID (as specified in the configuration) of an order to place. If provided as an array, all of the identified orders will be placed. example: dominos.medium_pan selector: text: diff --git a/homeassistant/components/dominos/strings.json b/homeassistant/components/dominos/strings.json new file mode 100644 index 00000000000000..0ceabd7abe8c48 --- /dev/null +++ b/homeassistant/components/dominos/strings.json @@ -0,0 +1,14 @@ +{ + "services": { + "order": { + "name": "Order", + "description": "Places a set of orders with Dominos Pizza.", + "fields": { + "order_entity_id": { + "name": "Order entity", + "description": "The ID (as specified in the configuration) of an order to place. If provided as an array, all of the identified orders will be placed." + } + } + } + } +} diff --git a/homeassistant/components/downloader/services.yaml b/homeassistant/components/downloader/services.yaml index cecb3804227a77..54d06db56273f2 100644 --- a/homeassistant/components/downloader/services.yaml +++ b/homeassistant/components/downloader/services.yaml @@ -1,29 +1,19 @@ download_file: - name: Download file - description: Download a file to the download location. fields: url: - name: URL - description: The URL of the file to download. required: true example: "http://example.org/myfile" selector: text: subdir: - name: Subdirectory - description: Download into subdirectory. example: "download_dir" selector: text: filename: - name: Filename - description: Determine the filename. example: "my_file_name" selector: text: overwrite: - name: Overwrite - description: Whether to overwrite the file or not. default: false selector: boolean: diff --git a/homeassistant/components/downloader/strings.json b/homeassistant/components/downloader/strings.json new file mode 100644 index 00000000000000..49a7388add2e05 --- /dev/null +++ b/homeassistant/components/downloader/strings.json @@ -0,0 +1,26 @@ +{ + "services": { + "download_file": { + "name": "Download file", + "description": "Downloads a file to the download location.", + "fields": { + "url": { + "name": "URL", + "description": "The URL of the file to download." + }, + "subdir": { + "name": "Subdirectory", + "description": "Download into subdirectory." + }, + "filename": { + "name": "Filename", + "description": "Determine the filename." + }, + "overwrite": { + "name": "Overwrite", + "description": "Whether to overwrite the file or not." + } + } + } + } +} diff --git a/homeassistant/components/duckdns/services.yaml b/homeassistant/components/duckdns/services.yaml index 6c8b5af8199986..485afa44a03796 100644 --- a/homeassistant/components/duckdns/services.yaml +++ b/homeassistant/components/duckdns/services.yaml @@ -1,10 +1,6 @@ set_txt: - name: Set TXT - description: Set the TXT record of your DuckDNS subdomain. fields: txt: - name: TXT - description: Payload for the TXT record. required: true example: "This domain name is reserved for use in documentation" selector: diff --git a/homeassistant/components/duckdns/strings.json b/homeassistant/components/duckdns/strings.json new file mode 100644 index 00000000000000..d560b760e47c5e --- /dev/null +++ b/homeassistant/components/duckdns/strings.json @@ -0,0 +1,14 @@ +{ + "services": { + "set_txt": { + "name": "Set TXT", + "description": "Sets the TXT record of your DuckDNS subdomain.", + "fields": { + "txt": { + "name": "TXT", + "description": "Payload for the TXT record." + } + } + } + } +} diff --git a/homeassistant/components/dynalite/services.yaml b/homeassistant/components/dynalite/services.yaml index d34335ca1d3447..97c5d9c24865e4 100644 --- a/homeassistant/components/dynalite/services.yaml +++ b/homeassistant/components/dynalite/services.yaml @@ -1,21 +1,16 @@ request_area_preset: - name: Request area preset - description: "Requests Dynalite to report the preset for an area." fields: host: - description: "Host gateway IP to send to or all configured gateways if not specified." example: "192.168.0.101" selector: text: area: - description: "Area to request the preset reported" required: true selector: number: min: 1 max: 9999 channel: - description: "Channel to request the preset to be reported from." default: 1 selector: number: @@ -23,26 +18,18 @@ request_area_preset: max: 9999 request_channel_level: - name: Request channel level - description: "Requests Dynalite to report the level of a specific channel." fields: host: - name: Host - description: "Host gateway IP to send to or all configured gateways if not specified." example: "192.168.0.101" selector: text: area: - name: Area - description: "Area for the requested channel" required: true selector: number: min: 1 max: 9999 channel: - name: Channel - description: "Channel to request the level for." required: true selector: number: diff --git a/homeassistant/components/dynalite/strings.json b/homeassistant/components/dynalite/strings.json index 8ad7deacd92ffa..512e00237d9852 100644 --- a/homeassistant/components/dynalite/strings.json +++ b/homeassistant/components/dynalite/strings.json @@ -14,5 +14,43 @@ "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]" } + }, + "services": { + "request_area_preset": { + "name": "Request area preset", + "description": "Requests Dynalite to report the preset for an area.", + "fields": { + "host": { + "name": "Host", + "description": "Host gateway IP to send to or all configured gateways if not specified." + }, + "area": { + "name": "Area", + "description": "Area to request the preset reported." + }, + "channel": { + "name": "Channel", + "description": "Channel to request the preset to be reported from." + } + } + }, + "request_channel_level": { + "name": "Request channel level", + "description": "Requests Dynalite to report the level of a specific channel.", + "fields": { + "host": { + "name": "Host", + "description": "Host gateway IP to send to or all configured gateways if not specified." + }, + "area": { + "name": "Area", + "description": "Area for the requested channel." + }, + "channel": { + "name": "Channel", + "description": "Channel to request the level for." + } + } + } } } From 5d5c58338fc8b65f383daffe41e5beff146ce118 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 11 Jul 2023 11:12:24 -1000 Subject: [PATCH 054/154] Fix ESPHome deep sleep devices staying unavailable after unexpected disconnect (#96353) --- homeassistant/components/esphome/manager.py | 6 +++ tests/components/esphome/conftest.py | 18 ++++++- tests/components/esphome/test_entity.py | 56 ++++++++++++++++++++- 3 files changed, 78 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/esphome/manager.py b/homeassistant/components/esphome/manager.py index b87d3ac38992a5..026d0315238b26 100644 --- a/homeassistant/components/esphome/manager.py +++ b/homeassistant/components/esphome/manager.py @@ -378,6 +378,12 @@ async def on_connect(self) -> None: assert cli.api_version is not None entry_data.api_version = cli.api_version entry_data.available = True + # Reset expected disconnect flag on successful reconnect + # as it will be flipped to False on unexpected disconnect. + # + # We use this to determine if a deep sleep device should + # be marked as unavailable or not. + entry_data.expected_disconnect = True if entry_data.device_info.name: assert reconnect_logic is not None, "Reconnect logic must be set" reconnect_logic.name = entry_data.device_info.name diff --git a/tests/components/esphome/conftest.py b/tests/components/esphome/conftest.py index 1dcdc559de7b61..f4b3bfa3ec7c83 100644 --- a/tests/components/esphome/conftest.py +++ b/tests/components/esphome/conftest.py @@ -154,6 +154,7 @@ def __init__(self, entry: MockConfigEntry) -> None: self.entry = entry self.state_callback: Callable[[EntityState], None] self.on_disconnect: Callable[[bool], None] + self.on_connect: Callable[[bool], None] def set_state_callback(self, state_callback: Callable[[EntityState], None]) -> None: """Set the state callback.""" @@ -171,6 +172,14 @@ async def mock_disconnect(self, expected_disconnect: bool) -> None: """Mock disconnecting.""" await self.on_disconnect(expected_disconnect) + def set_on_connect(self, on_connect: Callable[[], None]) -> None: + """Set the connect callback.""" + self.on_connect = on_connect + + async def mock_connect(self) -> None: + """Mock connecting.""" + await self.on_connect() + async def _mock_generic_device_entry( hass: HomeAssistant, @@ -226,6 +235,7 @@ def __init__(self, *args, **kwargs): """Init the mock.""" super().__init__(*args, **kwargs) mock_device.set_on_disconnect(kwargs["on_disconnect"]) + mock_device.set_on_connect(kwargs["on_connect"]) self._try_connect = self.mock_try_connect async def mock_try_connect(self): @@ -313,9 +323,15 @@ async def _mock_device( user_service: list[UserService], states: list[EntityState], entry: MockConfigEntry | None = None, + device_info: dict[str, Any] | None = None, ) -> MockESPHomeDevice: return await _mock_generic_device_entry( - hass, mock_client, {}, (entity_info, user_service), states, entry + hass, + mock_client, + device_info or {}, + (entity_info, user_service), + states, + entry, ) return _mock_device diff --git a/tests/components/esphome/test_entity.py b/tests/components/esphome/test_entity.py index 1a7d62f886b318..e268d065e21c0e 100644 --- a/tests/components/esphome/test_entity.py +++ b/tests/components/esphome/test_entity.py @@ -11,7 +11,7 @@ UserService, ) -from homeassistant.const import ATTR_RESTORED, STATE_ON +from homeassistant.const import ATTR_RESTORED, STATE_ON, STATE_UNAVAILABLE from homeassistant.core import HomeAssistant from .conftest import MockESPHomeDevice @@ -130,3 +130,57 @@ async def test_entity_info_object_ids( ) state = hass.states.get("binary_sensor.test_object_id_is_used") assert state is not None + + +async def test_deep_sleep_device( + hass: HomeAssistant, + mock_client: APIClient, + hass_storage: dict[str, Any], + mock_esphome_device: Callable[ + [APIClient, list[EntityInfo], list[UserService], list[EntityState]], + Awaitable[MockESPHomeDevice], + ], +) -> None: + """Test a deep sleep device.""" + entity_info = [ + BinarySensorInfo( + object_id="mybinary_sensor", + key=1, + name="my binary_sensor", + unique_id="my_binary_sensor", + ), + ] + states = [ + BinarySensorState(key=1, state=True, missing_state=False), + BinarySensorState(key=2, state=True, missing_state=False), + ] + user_service = [] + mock_device = await mock_esphome_device( + mock_client=mock_client, + entity_info=entity_info, + user_service=user_service, + states=states, + device_info={"has_deep_sleep": True}, + ) + state = hass.states.get("binary_sensor.test_mybinary_sensor") + assert state is not None + assert state.state == STATE_ON + + await mock_device.mock_disconnect(False) + await hass.async_block_till_done() + state = hass.states.get("binary_sensor.test_mybinary_sensor") + assert state is not None + assert state.state == STATE_UNAVAILABLE + + await mock_device.mock_connect() + await hass.async_block_till_done() + + state = hass.states.get("binary_sensor.test_mybinary_sensor") + assert state is not None + assert state.state == STATE_ON + + await mock_device.mock_disconnect(True) + await hass.async_block_till_done() + state = hass.states.get("binary_sensor.test_mybinary_sensor") + assert state is not None + assert state.state == STATE_ON From 2330af82a5a298363d48ce0926bcdac7d0dfd913 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 23:17:09 +0200 Subject: [PATCH 055/154] Migrate climate services to support translations (#96314) * Migrate climate services to support translations * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- .../components/climate/services.yaml | 84 ++-------- homeassistant/components/climate/strings.json | 153 ++++++++++++++++-- 2 files changed, 157 insertions(+), 80 deletions(-) diff --git a/homeassistant/components/climate/services.yaml b/homeassistant/components/climate/services.yaml index 33e114c87f5d40..405bb735b66a2b 100644 --- a/homeassistant/components/climate/services.yaml +++ b/homeassistant/components/climate/services.yaml @@ -1,8 +1,6 @@ # Describes the format for available climate services set_aux_heat: - name: Turn on/off auxiliary heater - description: Turn auxiliary heater on/off for climate device. target: entity: domain: climate @@ -10,15 +8,11 @@ set_aux_heat: - climate.ClimateEntityFeature.AUX_HEAT fields: aux_heat: - name: Auxiliary heating - description: New value of auxiliary heater. required: true selector: boolean: set_preset_mode: - name: Set preset mode - description: Set preset mode for climate device. target: entity: domain: climate @@ -26,16 +20,12 @@ set_preset_mode: - climate.ClimateEntityFeature.PRESET_MODE fields: preset_mode: - name: Preset mode - description: New value of preset mode. required: true example: "away" selector: text: set_temperature: - name: Set temperature - description: Set target temperature of climate device. target: entity: domain: climate @@ -44,8 +34,6 @@ set_temperature: - climate.ClimateEntityFeature.TARGET_TEMPERATURE_RANGE fields: temperature: - name: Temperature - description: New target temperature for HVAC. filter: supported_features: - climate.ClimateEntityFeature.TARGET_TEMPERATURE @@ -56,8 +44,6 @@ set_temperature: step: 0.1 mode: box target_temp_high: - name: Target temperature high - description: New target high temperature for HVAC. filter: supported_features: - climate.ClimateEntityFeature.TARGET_TEMPERATURE_RANGE @@ -69,8 +55,6 @@ set_temperature: step: 0.1 mode: box target_temp_low: - name: Target temperature low - description: New target low temperature for HVAC. filter: supported_features: - climate.ClimateEntityFeature.TARGET_TEMPERATURE_RANGE @@ -82,29 +66,18 @@ set_temperature: step: 0.1 mode: box hvac_mode: - name: HVAC mode - description: HVAC operation mode to set temperature to. selector: select: options: - - label: "Off" - value: "off" - - label: "Auto" - value: "auto" - - label: "Cool" - value: "cool" - - label: "Dry" - value: "dry" - - label: "Fan Only" - value: "fan_only" - - label: "Heat/Cool" - value: "heat_cool" - - label: "Heat" - value: "heat" - + - "off" + - "auto" + - "cool" + - "dry" + - "fan_only" + - "heat_cool" + - "heat" + translation_key: hvac_mode set_humidity: - name: Set target humidity - description: Set target humidity of climate device. target: entity: domain: climate @@ -112,8 +85,6 @@ set_humidity: - climate.ClimateEntityFeature.TARGET_HUMIDITY fields: humidity: - name: Humidity - description: New target humidity for climate device. required: true selector: number: @@ -122,8 +93,6 @@ set_humidity: unit_of_measurement: "%" set_fan_mode: - name: Set fan mode - description: Set fan operation for climate device. target: entity: domain: climate @@ -131,44 +100,29 @@ set_fan_mode: - climate.ClimateEntityFeature.FAN_MODE fields: fan_mode: - name: Fan mode - description: New value of fan mode. required: true example: "low" selector: text: set_hvac_mode: - name: Set HVAC mode - description: Set HVAC operation mode for climate device. target: entity: domain: climate fields: hvac_mode: - name: HVAC mode - description: New value of operation mode. selector: select: options: - - label: "Off" - value: "off" - - label: "Auto" - value: "auto" - - label: "Cool" - value: "cool" - - label: "Dry" - value: "dry" - - label: "Fan Only" - value: "fan_only" - - label: "Heat/Cool" - value: "heat_cool" - - label: "Heat" - value: "heat" - + - "off" + - "auto" + - "cool" + - "dry" + - "fan_only" + - "heat_cool" + - "heat" + translation_key: hvac_mode set_swing_mode: - name: Set swing mode - description: Set swing operation for climate device. target: entity: domain: climate @@ -176,23 +130,17 @@ set_swing_mode: - climate.ClimateEntityFeature.SWING_MODE fields: swing_mode: - name: Swing mode - description: New value of swing mode. required: true example: "horizontal" selector: text: turn_on: - name: Turn on - description: Turn climate device on. target: entity: domain: climate turn_off: - name: Turn off - description: Turn climate device off. target: entity: domain: climate diff --git a/homeassistant/components/climate/strings.json b/homeassistant/components/climate/strings.json index 8034799a6d0c5f..bfe0f490cda653 100644 --- a/homeassistant/components/climate/strings.json +++ b/homeassistant/components/climate/strings.json @@ -28,9 +28,15 @@ "fan_only": "Fan only" }, "state_attributes": { - "aux_heat": { "name": "Aux heat" }, - "current_humidity": { "name": "Current humidity" }, - "current_temperature": { "name": "Current temperature" }, + "aux_heat": { + "name": "Aux heat" + }, + "current_humidity": { + "name": "Current humidity" + }, + "current_temperature": { + "name": "Current temperature" + }, "fan_mode": { "name": "Fan mode", "state": { @@ -49,7 +55,9 @@ "fan_modes": { "name": "Fan modes" }, - "humidity": { "name": "Target humidity" }, + "humidity": { + "name": "Target humidity" + }, "hvac_action": { "name": "Current action", "state": { @@ -65,10 +73,18 @@ "hvac_modes": { "name": "HVAC modes" }, - "max_humidity": { "name": "Max target humidity" }, - "max_temp": { "name": "Max target temperature" }, - "min_humidity": { "name": "Min target humidity" }, - "min_temp": { "name": "Min target temperature" }, + "max_humidity": { + "name": "Max target humidity" + }, + "max_temp": { + "name": "Max target temperature" + }, + "min_humidity": { + "name": "Min target humidity" + }, + "min_temp": { + "name": "Min target temperature" + }, "preset_mode": { "name": "Preset", "state": { @@ -98,10 +114,123 @@ "swing_modes": { "name": "Swing modes" }, - "target_temp_high": { "name": "Upper target temperature" }, - "target_temp_low": { "name": "Lower target temperature" }, - "target_temp_step": { "name": "Target temperature step" }, - "temperature": { "name": "Target temperature" } + "target_temp_high": { + "name": "Upper target temperature" + }, + "target_temp_low": { + "name": "Lower target temperature" + }, + "target_temp_step": { + "name": "Target temperature step" + }, + "temperature": { + "name": "Target temperature" + } + } + } + }, + "services": { + "set_aux_heat": { + "name": "Turn on/off auxiliary heater", + "description": "Turns auxiliary heater on/off.", + "fields": { + "aux_heat": { + "name": "Auxiliary heating", + "description": "New value of auxiliary heater." + } + } + }, + "set_preset_mode": { + "name": "Set preset mode", + "description": "Sets preset mode.", + "fields": { + "preset_mode": { + "name": "Preset mode", + "description": "Preset mode." + } + } + }, + "set_temperature": { + "name": "Set target temperature", + "description": "Sets target temperature.", + "fields": { + "temperature": { + "name": "Temperature", + "description": "Target temperature." + }, + "target_temp_high": { + "name": "Target temperature high", + "description": "High target temperature." + }, + "target_temp_low": { + "name": "Target temperature low", + "description": "Low target temperature." + }, + "hvac_mode": { + "name": "HVAC mode", + "description": "HVAC operation mode." + } + } + }, + "set_humidity": { + "name": "Set target humidity", + "description": "Sets target humidity.", + "fields": { + "humidity": { + "name": "Humidity", + "description": "Target humidity." + } + } + }, + "set_fan_mode": { + "name": "Set fan mode", + "description": "Sets fan operation mode.", + "fields": { + "fan_mode": { + "name": "Fan mode", + "description": "Fan operation mode." + } + } + }, + "set_hvac_mode": { + "name": "Set HVAC mode", + "description": "Sets HVAC operation mode.", + "fields": { + "hvac_mode": { + "name": "HVAC mode", + "description": "HVAC operation mode." + } + } + }, + "set_swing_mode": { + "name": "Set swing mode", + "description": "Sets swing operation mode.", + "fields": { + "swing_mode": { + "name": "Swing mode", + "description": "Swing operation mode." + } + } + }, + "turn_on": { + "name": "Turn on", + "description": "Turns climate device on." + }, + "turn_off": { + "name": "Turn off", + "description": "Turns climate device off." + } + }, + "selector": { + "hvac_mode": { + "options": { + "off": "Off", + "auto": "Auto", + "cool": "Cool", + "dry": "Dry", + "fan_only": "Fan only", + "heat_cool": "Heat/cool", + "heat": "Heat" } } } From bde7d734b5ec673a20f8a369842865f2f83592fa Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 23:17:54 +0200 Subject: [PATCH 056/154] Migrate automation services to support translations (#96306) * Migrate automation services to support translations * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- .../components/automation/services.yaml | 14 -------- .../components/automation/strings.json | 34 +++++++++++++++++++ 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/homeassistant/components/automation/services.yaml b/homeassistant/components/automation/services.yaml index 62d0988d7702ee..6b3afdca33508f 100644 --- a/homeassistant/components/automation/services.yaml +++ b/homeassistant/components/automation/services.yaml @@ -1,46 +1,32 @@ # Describes the format for available automation services turn_on: - name: Turn on - description: Enable an automation. target: entity: domain: automation turn_off: - name: Turn off - description: Disable an automation. target: entity: domain: automation fields: stop_actions: - name: Stop actions - description: Stop currently running actions. default: true selector: boolean: toggle: - name: Toggle - description: Toggle (enable / disable) an automation. target: entity: domain: automation trigger: - name: Trigger - description: Trigger the actions of an automation. target: entity: domain: automation fields: skip_condition: - name: Skip conditions - description: Whether or not the conditions will be skipped. default: true selector: boolean: reload: - name: Reload - description: Reload the automation configuration. diff --git a/homeassistant/components/automation/strings.json b/homeassistant/components/automation/strings.json index 6f925fe090db89..cfeafa856d2e14 100644 --- a/homeassistant/components/automation/strings.json +++ b/homeassistant/components/automation/strings.json @@ -44,5 +44,39 @@ } } } + }, + "services": { + "turn_on": { + "name": "Turn on", + "description": "Enables an automation." + }, + "turn_off": { + "name": "Turn off", + "description": "Disables an automation.", + "fields": { + "stop_actions": { + "name": "Stop actions", + "description": "Stops currently running actions." + } + } + }, + "toggle": { + "name": "Toggle", + "description": "Toggles (enable / disable) an automation." + }, + "trigger": { + "name": "Trigger", + "description": "Triggers the actions of an automation.", + "fields": { + "skip_condition": { + "name": "Skip conditions", + "description": "Defines whether or not the conditions will be skipped." + } + } + }, + "reload": { + "name": "Reload", + "description": "Reloads the automation configuration." + } } } From 746832086013957d22370c230b632f50825ef66e Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 23:19:29 +0200 Subject: [PATCH 057/154] Migrate device_tracker services to support translations (#96320) * Migrate device_tracker services to support translations * Tweaks * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- .../components/device_tracker/services.yaml | 16 --------- .../components/device_tracker/strings.json | 36 +++++++++++++++++++ 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/homeassistant/components/device_tracker/services.yaml b/homeassistant/components/device_tracker/services.yaml index 22d89b42253c68..08ccbcf0b5a921 100644 --- a/homeassistant/components/device_tracker/services.yaml +++ b/homeassistant/components/device_tracker/services.yaml @@ -1,50 +1,34 @@ # Describes the format for available device tracker services see: - name: See - description: Control tracked device. fields: mac: - name: MAC address - description: MAC address of device example: "FF:FF:FF:FF:FF:FF" selector: text: dev_id: - name: Device ID - description: Id of device (find id in known_devices.yaml). example: "phonedave" selector: text: host_name: - name: Host name - description: Hostname of device example: "Dave" selector: text: location_name: - name: Location name - description: Name of location where device is located (not_home is away). example: "home" selector: text: gps: - name: GPS coordinates - description: GPS coordinates where device is located, specified by latitude and longitude. example: "[51.509802, -0.086692]" selector: object: gps_accuracy: - name: GPS accuracy - description: Accuracy of GPS coordinates. selector: number: min: 1 max: 100 unit_of_measurement: "%" battery: - name: Battery level - description: Battery level of device. selector: number: min: 0 diff --git a/homeassistant/components/device_tracker/strings.json b/homeassistant/components/device_tracker/strings.json index c15b9723c972ec..44c43219b82a2d 100644 --- a/homeassistant/components/device_tracker/strings.json +++ b/homeassistant/components/device_tracker/strings.json @@ -41,5 +41,41 @@ } } } + }, + "services": { + "see": { + "name": "See", + "description": "Records a seen tracked device.", + "fields": { + "mac": { + "name": "MAC address", + "description": "MAC address of the device." + }, + "dev_id": { + "name": "Device ID", + "description": "ID of the device (find the ID in `known_devices.yaml`)." + }, + "host_name": { + "name": "Hostname", + "description": "Hostname of the device." + }, + "location_name": { + "name": "Location", + "description": "Name of the location where the device is located. The options are: `home`, `not_home`, or the name of the zone." + }, + "gps": { + "name": "GPS coordinates", + "description": "GPS coordinates where the device is located, specified by latitude and longitude (for example: [51.513845, -0.100539])." + }, + "gps_accuracy": { + "name": "GPS accuracy", + "description": "Accuracy of the GPS coordinates." + }, + "battery": { + "name": "Battery level", + "description": "Battery level of the device." + } + } + } } } From b1e4bae3f0c63fcfbea8e532beb29b0c66ad3fd4 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 23:19:50 +0200 Subject: [PATCH 058/154] Migrate image_processing services to support translations (#96328) * Migrate image_processing services to support translations * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/image_processing/services.yaml | 2 -- homeassistant/components/image_processing/strings.json | 6 ++++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/image_processing/services.yaml b/homeassistant/components/image_processing/services.yaml index 620bd3518061f1..6309bafcfb936d 100644 --- a/homeassistant/components/image_processing/services.yaml +++ b/homeassistant/components/image_processing/services.yaml @@ -1,8 +1,6 @@ # Describes the format for available image processing services scan: - name: Scan - description: Process an image immediately target: entity: domain: image_processing diff --git a/homeassistant/components/image_processing/strings.json b/homeassistant/components/image_processing/strings.json index 861a2acc1f1166..2e630cfb4ded11 100644 --- a/homeassistant/components/image_processing/strings.json +++ b/homeassistant/components/image_processing/strings.json @@ -12,5 +12,11 @@ } } } + }, + "services": { + "scan": { + "name": "Scan", + "description": "Processes an image immediately." + } } } From 7d6148a295ea8ba2589f60b683b34af79e9bd799 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 23:20:07 +0200 Subject: [PATCH 059/154] Migrate button services to support translations (#96309) --- homeassistant/components/button/services.yaml | 2 -- homeassistant/components/button/strings.json | 6 ++++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/button/services.yaml b/homeassistant/components/button/services.yaml index 245368f9d5b33a..2f4d2c6fafe648 100644 --- a/homeassistant/components/button/services.yaml +++ b/homeassistant/components/button/services.yaml @@ -1,6 +1,4 @@ press: - name: Press - description: Press the button entity. target: entity: domain: button diff --git a/homeassistant/components/button/strings.json b/homeassistant/components/button/strings.json index a92a5a0f38a7ad..39456cdf42757a 100644 --- a/homeassistant/components/button/strings.json +++ b/homeassistant/components/button/strings.json @@ -21,5 +21,11 @@ "update": { "name": "Update" } + }, + "services": { + "press": { + "name": "Press", + "description": "Press the button entity." + } } } From f3b0c56c8c9a5f7104ff9613ce50a04b35702dc8 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 23:20:40 +0200 Subject: [PATCH 060/154] Migrate calendar services to support translations (#96310) * Migrate camera services to support translations * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- .../components/calendar/services.yaml | 26 --------- .../components/calendar/strings.json | 58 +++++++++++++++++++ 2 files changed, 58 insertions(+), 26 deletions(-) diff --git a/homeassistant/components/calendar/services.yaml b/homeassistant/components/calendar/services.yaml index 1f4d6aa3152a65..712d6ad88232e7 100644 --- a/homeassistant/components/calendar/services.yaml +++ b/homeassistant/components/calendar/services.yaml @@ -1,6 +1,4 @@ create_event: - name: Create event - description: Add a new calendar event. target: entity: domain: calendar @@ -8,73 +6,49 @@ create_event: - calendar.CalendarEntityFeature.CREATE_EVENT fields: summary: - name: Summary - description: Defines the short summary or subject for the event required: true example: "Department Party" selector: text: description: - name: Description - description: A more complete description of the event than that provided by the summary. example: "Meeting to provide technical review for 'Phoenix' design." selector: text: start_date_time: - name: Start time - description: The date and time the event should start. example: "2022-03-22 20:00:00" selector: datetime: end_date_time: - name: End time - description: The date and time the event should end. example: "2022-03-22 22:00:00" selector: datetime: start_date: - name: Start date - description: The date the all-day event should start. example: "2022-03-22" selector: date: end_date: - name: End date - description: The date the all-day event should end (exclusive). example: "2022-03-23" selector: date: in: - name: In - description: Days or weeks that you want to create the event in. example: '{"days": 2} or {"weeks": 2}' location: - name: Location - description: The location of the event. example: "Conference Room - F123, Bldg. 002" selector: text: list_events: - name: List event - description: List events on a calendar within a time range. target: entity: domain: calendar fields: start_date_time: - name: Start time - description: Return active events after this time (exclusive). When not set, defaults to now. example: "2022-03-22 20:00:00" selector: datetime: end_date_time: - name: End time - description: Return active events before this time (exclusive). Cannot be used with 'duration'. example: "2022-03-22 22:00:00" selector: datetime: duration: - name: Duration - description: Return active events from start_date_time until the specified duration. selector: duration: diff --git a/homeassistant/components/calendar/strings.json b/homeassistant/components/calendar/strings.json index 898953c18acdcc..81334c12379667 100644 --- a/homeassistant/components/calendar/strings.json +++ b/homeassistant/components/calendar/strings.json @@ -32,5 +32,63 @@ } } } + }, + "services": { + "create_event": { + "name": "Create event", + "description": "Adds a new calendar event.", + "fields": { + "summary": { + "name": "Summary", + "description": "Defines the short summary or subject for the event." + }, + "description": { + "name": "Description", + "description": "A more complete description of the event than the one provided by the summary." + }, + "start_date_time": { + "name": "Start time", + "description": "The date and time the event should start." + }, + "end_date_time": { + "name": "End time", + "description": "The date and time the event should end." + }, + "start_date": { + "name": "Start date", + "description": "The date the all-day event should start." + }, + "end_date": { + "name": "End date", + "description": "The date the all-day event should end (exclusive)." + }, + "in": { + "name": "In", + "description": "Days or weeks that you want to create the event in." + }, + "location": { + "name": "Location", + "description": "The location of the event." + } + } + }, + "list_events": { + "name": "List event", + "description": "Lists events on a calendar within a time range.", + "fields": { + "start_date_time": { + "name": "Start time", + "description": "Returns active events after this time (exclusive). When not set, defaults to now." + }, + "end_date_time": { + "name": "End time", + "description": "Returns active events before this time (exclusive). Cannot be used with 'duration'." + }, + "duration": { + "name": "Duration", + "description": "Returns active events from start_date_time until the specified duration." + } + } + } } } From e4af29342860e31f203391a4750c426f0ae43f58 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 23:21:00 +0200 Subject: [PATCH 061/154] Migrate cloud services to support translations (#96319) * Migrate cloud services to support translations * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/cloud/services.yaml | 5 ----- homeassistant/components/cloud/strings.json | 10 ++++++++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/cloud/services.yaml b/homeassistant/components/cloud/services.yaml index 1b676ea6be96e9..b54d35d4221cd8 100644 --- a/homeassistant/components/cloud/services.yaml +++ b/homeassistant/components/cloud/services.yaml @@ -1,9 +1,4 @@ # Describes the format for available cloud services remote_connect: - name: Remote connect - description: Make instance UI available outside over NabuCasa cloud - remote_disconnect: - name: Remote disconnect - description: Disconnect UI from NabuCasa cloud diff --git a/homeassistant/components/cloud/strings.json b/homeassistant/components/cloud/strings.json index a3cf7fe04576c2..aba2e770bc91f7 100644 --- a/homeassistant/components/cloud/strings.json +++ b/homeassistant/components/cloud/strings.json @@ -30,5 +30,15 @@ } } } + }, + "services": { + "remote_connect": { + "name": "Remote connect", + "description": "Makes the instance UI accessible from outside of the local network by using Home Assistant Cloud." + }, + "remote_disconnect": { + "name": "Remote disconnect", + "description": "Disconnects the Home Assistant UI from the Home Assistant Cloud. You will no longer be able to access your Home Assistant instance from outside your local network." + } } } From ea3be7a7891ea5dcb072b4b6247c3e27d882820a Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 11 Jul 2023 23:57:29 +0200 Subject: [PATCH 062/154] Migrate integration services (E-F) to support translations (#96367) --- homeassistant/components/demo/services.yaml | 2 - homeassistant/components/demo/strings.json | 6 + homeassistant/components/ebusd/services.yaml | 4 - homeassistant/components/ebusd/strings.json | 14 ++ homeassistant/components/ecobee/services.yaml | 62 -------- homeassistant/components/ecobee/strings.json | 124 +++++++++++++++ .../components/eight_sleep/services.yaml | 6 - .../components/eight_sleep/strings.json | 16 ++ homeassistant/components/elgato/services.yaml | 4 - homeassistant/components/elgato/strings.json | 6 + homeassistant/components/elkm1/services.yaml | 60 -------- homeassistant/components/elkm1/strings.json | 144 ++++++++++++++++++ .../environment_canada/services.yaml | 4 - .../environment_canada/strings.json | 12 ++ .../components/envisalink/services.yaml | 16 -- .../components/envisalink/strings.json | 32 ++++ homeassistant/components/epson/services.yaml | 4 - homeassistant/components/epson/strings.json | 12 ++ .../components/evohome/services.yaml | 38 ----- homeassistant/components/evohome/strings.json | 58 +++++++ homeassistant/components/ezviz/services.yaml | 22 --- homeassistant/components/ezviz/strings.json | 54 +++++++ .../components/facebox/services.yaml | 8 - homeassistant/components/facebox/strings.json | 22 +++ .../components/fastdotcom/services.yaml | 2 - .../components/fastdotcom/strings.json | 8 + homeassistant/components/ffmpeg/services.yaml | 12 -- homeassistant/components/ffmpeg/strings.json | 34 +++++ homeassistant/components/flo/services.yaml | 12 -- homeassistant/components/flo/strings.json | 28 ++++ .../components/flux_led/services.yaml | 18 --- .../components/flux_led/strings.json | 68 +++++++++ homeassistant/components/foscam/services.yaml | 7 - homeassistant/components/foscam/strings.json | 26 ++++ .../components/freebox/services.yaml | 2 - homeassistant/components/freebox/strings.json | 6 + homeassistant/components/fritz/services.yaml | 20 --- homeassistant/components/fritz/strings.json | 130 +++++++++++++--- .../components/fully_kiosk/services.yaml | 14 -- .../components/fully_kiosk/strings.json | 36 +++++ 40 files changed, 816 insertions(+), 337 deletions(-) create mode 100644 homeassistant/components/ebusd/strings.json create mode 100644 homeassistant/components/envisalink/strings.json create mode 100644 homeassistant/components/evohome/strings.json create mode 100644 homeassistant/components/facebox/strings.json create mode 100644 homeassistant/components/fastdotcom/strings.json create mode 100644 homeassistant/components/ffmpeg/strings.json diff --git a/homeassistant/components/demo/services.yaml b/homeassistant/components/demo/services.yaml index a09b4498035bf6..300ea37f8053cd 100644 --- a/homeassistant/components/demo/services.yaml +++ b/homeassistant/components/demo/services.yaml @@ -1,3 +1 @@ randomize_device_tracker_data: - name: Randomize device tracker data - description: Demonstrates using a device tracker to see where devices are located diff --git a/homeassistant/components/demo/strings.json b/homeassistant/components/demo/strings.json index 3794b27cc0ea01..2dfb3465d68655 100644 --- a/homeassistant/components/demo/strings.json +++ b/homeassistant/components/demo/strings.json @@ -75,5 +75,11 @@ } } } + }, + "services": { + "randomize_device_tracker_data": { + "name": "Randomize device tracker data", + "description": "Demonstrates using a device tracker to see where devices are located." + } } } diff --git a/homeassistant/components/ebusd/services.yaml b/homeassistant/components/ebusd/services.yaml index dc356bec22618e..6615e947f287c9 100644 --- a/homeassistant/components/ebusd/services.yaml +++ b/homeassistant/components/ebusd/services.yaml @@ -1,10 +1,6 @@ write: - name: Write - description: Call ebusd write command. fields: call: - name: Call - description: Property name and value to set required: true example: '{"name": "Hc1MaxFlowTempDesired", "value": 21}' selector: diff --git a/homeassistant/components/ebusd/strings.json b/homeassistant/components/ebusd/strings.json new file mode 100644 index 00000000000000..4097be023933f0 --- /dev/null +++ b/homeassistant/components/ebusd/strings.json @@ -0,0 +1,14 @@ +{ + "services": { + "write": { + "name": "Write", + "description": "Calls the ebusd write command.", + "fields": { + "call": { + "name": "Call", + "description": "Property name and value to set." + } + } + } + } +} diff --git a/homeassistant/components/ecobee/services.yaml b/homeassistant/components/ecobee/services.yaml index aba579891195bf..a184f4227253cc 100644 --- a/homeassistant/components/ecobee/services.yaml +++ b/homeassistant/components/ecobee/services.yaml @@ -1,28 +1,17 @@ create_vacation: - name: Create vacation - description: >- - Create a vacation on the selected thermostat. Note: start/end date and time must all be specified - together for these parameters to have an effect. If start/end date and time are not specified, the - vacation will start immediately and last 14 days (unless deleted earlier). fields: entity_id: - name: Entity - description: ecobee thermostat on which to create the vacation. required: true selector: entity: integration: ecobee domain: climate vacation_name: - name: Vacation name - description: Name of the vacation to create; must be unique on the thermostat. required: true example: "Skiing" selector: text: cool_temp: - name: Cool temperature - description: Cooling temperature during the vacation. required: true selector: number: @@ -31,8 +20,6 @@ create_vacation: step: 0.5 unit_of_measurement: "°" heat_temp: - name: Heat temperature - description: Heating temperature during the vacation. required: true selector: number: @@ -41,36 +28,22 @@ create_vacation: step: 0.5 unit_of_measurement: "°" start_date: - name: Start date - description: >- - Date the vacation starts in the YYYY-MM-DD format (optional, immediately if not provided along with - start_time, end_date, and end_time). example: "2019-03-15" selector: text: start_time: - name: start time - description: Time the vacation starts, in the local time of the thermostat, in the 24-hour format "HH:MM:SS" example: "20:00:00" selector: time: end_date: - name: End date - description: >- - Date the vacation ends in the YYYY-MM-DD format (optional, 14 days from now if not provided along with - start_date, start_time, and end_time). example: "2019-03-20" selector: text: end_time: - name: End time - description: Time the vacation ends, in the local time of the thermostat, in the 24-hour format "HH:MM:SS" example: "20:00:00" selector: time: fan_mode: - name: Fan mode - description: Fan mode of the thermostat during the vacation. default: "auto" selector: select: @@ -78,8 +51,6 @@ create_vacation: - "on" - "auto" fan_min_on_time: - name: Fan minimum on time - description: Minimum number of minutes to run the fan each hour (0 to 60) during the vacation. default: 0 selector: number: @@ -88,13 +59,8 @@ create_vacation: unit_of_measurement: minutes delete_vacation: - name: Delete vacation - description: >- - Delete a vacation on the selected thermostat. fields: entity_id: - name: Entity - description: ecobee thermostat on which to delete the vacation. required: true example: "climate.kitchen" selector: @@ -102,45 +68,31 @@ delete_vacation: integration: ecobee domain: climate vacation_name: - name: Vacation name - description: Name of the vacation to delete. required: true example: "Skiing" selector: text: resume_program: - name: Resume program - description: Resume the programmed schedule. fields: entity_id: - name: Entity - description: Name(s) of entities to change. selector: entity: integration: ecobee domain: climate resume_all: - name: Resume all - description: Resume all events and return to the scheduled program. default: false selector: boolean: set_fan_min_on_time: - name: Set fan minimum on time - description: Set the minimum fan on time. fields: entity_id: - name: Entity - description: Name(s) of entities to change. selector: entity: integration: ecobee domain: climate fan_min_on_time: - name: Fan minimum on time - description: New value of fan min on time. required: true selector: number: @@ -149,50 +101,36 @@ set_fan_min_on_time: unit_of_measurement: minutes set_dst_mode: - name: Set Daylight savings time mode - description: Enable/disable automatic daylight savings time. target: entity: integration: ecobee domain: climate fields: dst_enabled: - name: Daylight savings time enabled - description: Enable automatic daylight savings time. required: true selector: boolean: set_mic_mode: - name: Set mic mode - description: Enable/disable Alexa mic (only for Ecobee 4). target: entity: integration: ecobee domain: climate fields: mic_enabled: - name: Mic enabled - description: Enable Alexa mic. required: true selector: boolean: set_occupancy_modes: - name: Set occupancy modes - description: Enable/disable Smart Home/Away and Follow Me modes. target: entity: integration: ecobee domain: climate fields: auto_away: - name: Auto away - description: Enable Smart Home/Away mode. selector: boolean: follow_me: - name: Follow me - description: Enable Follow Me mode. selector: boolean: diff --git a/homeassistant/components/ecobee/strings.json b/homeassistant/components/ecobee/strings.json index 647ea55e3115fd..05ae600d4b733a 100644 --- a/homeassistant/components/ecobee/strings.json +++ b/homeassistant/components/ecobee/strings.json @@ -28,5 +28,129 @@ "name": "Ventilator min time away" } } + }, + "services": { + "create_vacation": { + "name": "Create vacation", + "description": "Creates a vacation on the selected thermostat. Note: start/end date and time must all be specified together for these parameters to have an effect. If start/end date and time are not specified, the vacation will start immediately and last 14 days (unless deleted earlier).", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Ecobee thermostat on which to create the vacation." + }, + "vacation_name": { + "name": "Vacation name", + "description": "Name of the vacation to create; must be unique on the thermostat." + }, + "cool_temp": { + "name": "Cool temperature", + "description": "Cooling temperature during the vacation." + }, + "heat_temp": { + "name": "Heat temperature", + "description": "Heating temperature during the vacation." + }, + "start_date": { + "name": "Start date", + "description": "Date the vacation starts in the YYYY-MM-DD format (optional, immediately if not provided along with start_time, end_date, and end_time)." + }, + "start_time": { + "name": "Start time", + "description": "Time the vacation starts, in the local time of the thermostat, in the 24-hour format \"HH:MM:SS\"." + }, + "end_date": { + "name": "End date", + "description": "Date the vacation ends in the YYYY-MM-DD format (optional, 14 days from now if not provided along with start_date, start_time, and end_time)." + }, + "end_time": { + "name": "End time", + "description": "Time the vacation ends, in the local time of the thermostat, in the 24-hour format \"HH:MM:SS\"." + }, + "fan_mode": { + "name": "Fan mode", + "description": "Fan mode of the thermostat during the vacation." + }, + "fan_min_on_time": { + "name": "Fan minimum on time", + "description": "Minimum number of minutes to run the fan each hour (0 to 60) during the vacation." + } + } + }, + "delete_vacation": { + "name": "Delete vacation", + "description": "Deletes a vacation on the selected thermostat.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Ecobee thermostat on which to delete the vacation." + }, + "vacation_name": { + "name": "Vacation name", + "description": "Name of the vacation to delete." + } + } + }, + "resume_program": { + "name": "Resume program", + "description": "Resumes the programmed schedule.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name(s) of entities to change." + }, + "resume_all": { + "name": "Resume all", + "description": "Resume all events and return to the scheduled program." + } + } + }, + "set_fan_min_on_time": { + "name": "Set fan minimum on time", + "description": "Sets the minimum fan on time.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name(s) of entities to change." + }, + "fan_min_on_time": { + "name": "Fan minimum on time", + "description": "New value of fan min on time." + } + } + }, + "set_dst_mode": { + "name": "Set Daylight savings time mode", + "description": "Enables/disables automatic daylight savings time.", + "fields": { + "dst_enabled": { + "name": "Daylight savings time enabled", + "description": "Enable automatic daylight savings time." + } + } + }, + "set_mic_mode": { + "name": "Set mic mode", + "description": "Enables/disables Alexa mic (only for Ecobee 4).", + "fields": { + "mic_enabled": { + "name": "Mic enabled", + "description": "Enable Alexa mic." + } + } + }, + "set_occupancy_modes": { + "name": "Set occupancy modes", + "description": "Enables/disables Smart Home/Away and Follow Me modes.", + "fields": { + "auto_away": { + "name": "Auto away", + "description": "Enable Smart Home/Away mode." + }, + "follow_me": { + "name": "Follow me", + "description": "Enable Follow Me mode." + } + } + } } } diff --git a/homeassistant/components/eight_sleep/services.yaml b/homeassistant/components/eight_sleep/services.yaml index 39b960a6f7c1f1..b191187bb0ac6e 100644 --- a/homeassistant/components/eight_sleep/services.yaml +++ b/homeassistant/components/eight_sleep/services.yaml @@ -1,14 +1,10 @@ heat_set: - name: Heat set - description: Set heating/cooling level for eight sleep. target: entity: integration: eight_sleep domain: sensor fields: duration: - name: Duration - description: Duration to heat/cool at the target level in seconds. required: true selector: number: @@ -16,8 +12,6 @@ heat_set: max: 28800 unit_of_measurement: seconds target: - name: Target - description: Target cooling/heating level from -100 to 100. required: true selector: number: diff --git a/homeassistant/components/eight_sleep/strings.json b/homeassistant/components/eight_sleep/strings.json index 21accc53a06a17..bd2b4f11b9d966 100644 --- a/homeassistant/components/eight_sleep/strings.json +++ b/homeassistant/components/eight_sleep/strings.json @@ -15,5 +15,21 @@ "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", "cannot_connect": "Cannot connect to Eight Sleep cloud: {error}" } + }, + "services": { + "heat_set": { + "name": "Heat set", + "description": "Sets heating/cooling level for eight sleep.", + "fields": { + "duration": { + "name": "Duration", + "description": "Duration to heat/cool at the target level in seconds." + }, + "target": { + "name": "Target", + "description": "Target cooling/heating level from -100 to 100." + } + } + } } } diff --git a/homeassistant/components/elgato/services.yaml b/homeassistant/components/elgato/services.yaml index 05d341a704130e..2037633ff71f6f 100644 --- a/homeassistant/components/elgato/services.yaml +++ b/homeassistant/components/elgato/services.yaml @@ -1,8 +1,4 @@ identify: - name: Identify - description: >- - Identify an Elgato Light. Blinks the light, which can be useful - for, e.g., a visual notification. target: entity: integration: elgato diff --git a/homeassistant/components/elgato/strings.json b/homeassistant/components/elgato/strings.json index 8a2f20f209f8bf..e6b16215793c42 100644 --- a/homeassistant/components/elgato/strings.json +++ b/homeassistant/components/elgato/strings.json @@ -45,5 +45,11 @@ "name": "Energy saving" } } + }, + "services": { + "identify": { + "name": "Identify", + "description": "Identifies an Elgato Light. Blinks the light, which can be useful for, e.g., a visual notification." + } } } diff --git a/homeassistant/components/elkm1/services.yaml b/homeassistant/components/elkm1/services.yaml index 1f130416363102..1f3bb8ffebb030 100644 --- a/homeassistant/components/elkm1/services.yaml +++ b/homeassistant/components/elkm1/services.yaml @@ -1,197 +1,143 @@ alarm_bypass: - name: Alarm bypass - description: Bypass all zones for the area. target: entity: integration: elkm1 domain: alarm_control_panel fields: code: - name: Code - description: An code to authorize the bypass of the alarm control panel. required: true example: 4242 selector: text: alarm_clear_bypass: - name: Alarm clear bypass - description: Remove bypass on all zones for the area. target: entity: integration: elkm1 domain: alarm_control_panel fields: code: - name: Code - description: An code to authorize the bypass clear of the alarm control panel. required: true example: 4242 selector: text: alarm_arm_home_instant: - name: Alarm are home instant - description: Arm the ElkM1 in home instant mode. target: entity: integration: elkm1 domain: alarm_control_panel fields: code: - name: Code - description: An code to arm the alarm control panel. required: true example: 1234 selector: text: alarm_arm_night_instant: - name: Alarm arm night instant - description: Arm the ElkM1 in night instant mode. target: entity: integration: elkm1 domain: alarm_control_panel fields: code: - name: Code - description: An code to arm the alarm control panel. required: true example: 1234 selector: text: alarm_arm_vacation: - name: Alarm arm vacation - description: Arm the ElkM1 in vacation mode. target: entity: integration: elkm1 domain: alarm_control_panel fields: code: - name: Code - description: An code to arm the alarm control panel. required: true example: 1234 selector: text: alarm_display_message: - name: Alarm display message - description: Display a message on all of the ElkM1 keypads for an area. target: entity: integration: elkm1 domain: alarm_control_panel fields: clear: - name: Clear - description: 0=clear message, 1=clear message with * key, 2=Display until timeout default: 2 selector: number: min: 0 max: 2 beep: - name: Beep - description: 0=no beep, 1=beep default: 0 selector: boolean: timeout: - name: Timeout - description: Time to display message, 0=forever, max 65535 default: 0 selector: number: min: 0 max: 65535 line1: - name: Line 1 - description: Up to 16 characters of text (truncated if too long). example: The answer to life. default: "" selector: text: line2: - name: Line 2 - description: Up to 16 characters of text (truncated if too long). example: the universe, and everything. default: "" selector: text: set_time: - name: Set time - description: Set the time for the panel. fields: prefix: - name: Prefix - description: Prefix for the panel. example: gatehouse selector: text: speak_phrase: - name: Speak phrase - description: Speak a phrase. See list of phrases in ElkM1 ASCII Protocol documentation. fields: number: - name: Phrase number - description: Phrase number to speak. required: true example: 42 selector: text: prefix: - name: Prefix - description: Prefix to identify panel when multiple panels configured. example: gatehouse default: "" selector: text: speak_word: - name: Speak word - description: Speak a word. See list of words in ElkM1 ASCII Protocol documentation. fields: number: - name: Word number - description: Word number to speak. required: true selector: number: min: 1 max: 473 prefix: - name: Prefix - description: Prefix to identify panel when multiple panels configured. example: gatehouse default: "" selector: text: sensor_counter_refresh: - name: Sensor counter refresh - description: Refresh the value of a counter from the panel. target: entity: integration: elkm1 domain: sensor sensor_counter_set: - name: Sensor counter set - description: Set the value of a counter on the panel. target: entity: integration: elkm1 domain: sensor fields: value: - name: Value - description: Value to set the counter to. required: true selector: number: @@ -199,24 +145,18 @@ sensor_counter_set: max: 65536 sensor_zone_bypass: - name: Sensor zone bypass - description: Bypass zone. target: entity: integration: elkm1 domain: sensor fields: code: - name: Code - description: An code to authorize the bypass of the zone. required: true example: 4242 selector: text: sensor_zone_trigger: - name: Sensor zone trigger - description: Trigger zone. target: entity: integration: elkm1 diff --git a/homeassistant/components/elkm1/strings.json b/homeassistant/components/elkm1/strings.json index d1871c7536c649..5ef15827eb9ea8 100644 --- a/homeassistant/components/elkm1/strings.json +++ b/homeassistant/components/elkm1/strings.json @@ -45,5 +45,149 @@ "already_configured": "An ElkM1 with this prefix is already configured", "address_already_configured": "An ElkM1 with this address is already configured" } + }, + "services": { + "alarm_bypass": { + "name": "Alarm bypass", + "description": "Bypasses all zones for the area.", + "fields": { + "code": { + "name": "Code", + "description": "An code to authorize the bypass of the alarm control panel." + } + } + }, + "alarm_clear_bypass": { + "name": "Alarm clear bypass", + "description": "Removes bypass on all zones for the area.", + "fields": { + "code": { + "name": "Code", + "description": "An code to authorize the bypass clear of the alarm control panel." + } + } + }, + "alarm_arm_home_instant": { + "name": "Alarm are home instant", + "description": "Arms the ElkM1 in home instant mode.", + "fields": { + "code": { + "name": "Code", + "description": "An code to arm the alarm control panel." + } + } + }, + "alarm_arm_night_instant": { + "name": "Alarm arm night instant", + "description": "Arms the ElkM1 in night instant mode.", + "fields": { + "code": { + "name": "Code", + "description": "An code to arm the alarm control panel." + } + } + }, + "alarm_arm_vacation": { + "name": "Alarm arm vacation", + "description": "Arm the ElkM1 in vacation mode.", + "fields": { + "code": { + "name": "Code", + "description": "An code to arm the alarm control panel." + } + } + }, + "alarm_display_message": { + "name": "Alarm display message", + "description": "Displays a message on all of the ElkM1 keypads for an area.", + "fields": { + "clear": { + "name": "Clear", + "description": "0=clear message, 1=clear message with * key, 2=Display until timeout." + }, + "beep": { + "name": "Beep", + "description": "0=no beep, 1=beep." + }, + "timeout": { + "name": "Timeout", + "description": "Time to display message, 0=forever, max 65535." + }, + "line1": { + "name": "Line 1", + "description": "Up to 16 characters of text (truncated if too long)." + }, + "line2": { + "name": "Line 2", + "description": "Up to 16 characters of text (truncated if too long)." + } + } + }, + "set_time": { + "name": "Set time", + "description": "Sets the time for the panel.", + "fields": { + "prefix": { + "name": "Prefix", + "description": "Prefix for the panel." + } + } + }, + "speak_phrase": { + "name": "Speak phrase", + "description": "Speaks a phrase. See list of phrases in ElkM1 ASCII Protocol documentation.", + "fields": { + "number": { + "name": "Phrase number", + "description": "Phrase number to speak." + }, + "prefix": { + "name": "Prefix", + "description": "Prefix to identify panel when multiple panels configured." + } + } + }, + "speak_word": { + "name": "Speak word", + "description": "Speaks a word. See list of words in ElkM1 ASCII Protocol documentation.", + "fields": { + "number": { + "name": "Word number", + "description": "Word number to speak." + }, + "prefix": { + "name": "Prefix", + "description": "Prefix to identify panel when multiple panels configured." + } + } + }, + "sensor_counter_refresh": { + "name": "Sensor counter refresh", + "description": "Refreshes the value of a counter from the panel." + }, + "sensor_counter_set": { + "name": "Sensor counter set", + "description": "Sets the value of a counter on the panel.", + "fields": { + "value": { + "name": "Value", + "description": "Value to set the counter to." + } + } + }, + "sensor_zone_bypass": { + "name": "Sensor zone bypass", + "description": "Bypasses zone.", + "fields": { + "code": { + "name": "Code", + "description": "An code to authorize the bypass of the zone." + } + } + }, + "sensor_zone_trigger": { + "name": "Sensor zone trigger", + "description": "Triggers zone." + } } } diff --git a/homeassistant/components/environment_canada/services.yaml b/homeassistant/components/environment_canada/services.yaml index 09f95f16a44de3..4293b313f5ce62 100644 --- a/homeassistant/components/environment_canada/services.yaml +++ b/homeassistant/components/environment_canada/services.yaml @@ -1,14 +1,10 @@ set_radar_type: - name: Set radar type - description: Set the type of radar image to retrieve. target: entity: integration: environment_canada domain: camera fields: radar_type: - name: Radar type - description: The type of radar image to display. required: true example: Snow selector: diff --git a/homeassistant/components/environment_canada/strings.json b/homeassistant/components/environment_canada/strings.json index d30124ddf5af69..eb9ec24dad0f98 100644 --- a/homeassistant/components/environment_canada/strings.json +++ b/homeassistant/components/environment_canada/strings.json @@ -117,5 +117,17 @@ "name": "Forecast" } } + }, + "services": { + "set_radar_type": { + "name": "Set radar type", + "description": "Sets the type of radar image to retrieve.", + "fields": { + "radar_type": { + "name": "Radar type", + "description": "The type of radar image to display." + } + } + } } } diff --git a/homeassistant/components/envisalink/services.yaml b/homeassistant/components/envisalink/services.yaml index b15a3b94e014ee..6751a3ecc560f7 100644 --- a/homeassistant/components/envisalink/services.yaml +++ b/homeassistant/components/envisalink/services.yaml @@ -1,43 +1,27 @@ # Describes the format for available Envisalink services. alarm_keypress: - name: Alarm keypress - description: Send custom keypresses to the alarm. fields: entity_id: - name: Entity - description: Name of the alarm control panel to trigger. required: true selector: entity: integration: envisalink domain: alarm_control_panel keypress: - name: Keypress - description: "String to send to the alarm panel (1-6 characters)." required: true example: "*71" selector: text: invoke_custom_function: - name: Invoke custom function - description: > - Allows users with DSC panels to trigger a PGM output (1-4). - Note that you need to specify the alarm panel's "code" parameter for this to work. fields: partition: - name: Partition - description: > - The alarm panel partition to trigger the PGM output on. - Typically this is just "1". required: true example: "1" selector: text: pgm: - name: PGM - description: The PGM number to trigger on the alarm panel. required: true selector: number: diff --git a/homeassistant/components/envisalink/strings.json b/homeassistant/components/envisalink/strings.json new file mode 100644 index 00000000000000..a539c890169141 --- /dev/null +++ b/homeassistant/components/envisalink/strings.json @@ -0,0 +1,32 @@ +{ + "services": { + "alarm_keypress": { + "name": "Alarm keypress", + "description": "Sends custom keypresses to the alarm.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name of the alarm control panel to trigger." + }, + "keypress": { + "name": "Keypress", + "description": "String to send to the alarm panel (1-6 characters)." + } + } + }, + "invoke_custom_function": { + "name": "Invoke custom function", + "description": "Allows users with DSC panels to trigger a PGM output (1-4). Note that you need to specify the alarm panel's \"code\" parameter for this to work.\n.", + "fields": { + "partition": { + "name": "Partition", + "description": "The alarm panel partition to trigger the PGM output on. Typically this is just \"1\".\n." + }, + "pgm": { + "name": "PGM", + "description": "The PGM number to trigger on the alarm panel." + } + } + } + } +} diff --git a/homeassistant/components/epson/services.yaml b/homeassistant/components/epson/services.yaml index 37add1bc20202e..94038aab408deb 100644 --- a/homeassistant/components/epson/services.yaml +++ b/homeassistant/components/epson/services.yaml @@ -1,14 +1,10 @@ select_cmode: - name: Select color mode - description: Select Color mode of Epson projector target: entity: integration: epson domain: media_player fields: cmode: - name: Color mode - description: Name of Cmode required: true example: "cinema" selector: diff --git a/homeassistant/components/epson/strings.json b/homeassistant/components/epson/strings.json index 9716153958b8b5..4e3780322e9301 100644 --- a/homeassistant/components/epson/strings.json +++ b/homeassistant/components/epson/strings.json @@ -15,5 +15,17 @@ "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "powered_off": "Is projector turned on? You need to turn on projector for initial configuration." } + }, + "services": { + "select_cmode": { + "name": "Select color mode", + "description": "Selects color mode of Epson projector.", + "fields": { + "cmode": { + "name": "Color mode", + "description": "Name of Cmode." + } + } + } } } diff --git a/homeassistant/components/evohome/services.yaml b/homeassistant/components/evohome/services.yaml index 52428dd5e1ea7b..a16395ad6c0278 100644 --- a/homeassistant/components/evohome/services.yaml +++ b/homeassistant/components/evohome/services.yaml @@ -2,14 +2,8 @@ # Describes the format for available services set_system_mode: - name: Set system mode - description: >- - Set the system mode, either indefinitely, or for a specified period of time, after - which it will revert to Auto. Not all systems support all modes. fields: mode: - name: Mode - description: "Mode to set thermostat." example: Away selector: select: @@ -21,41 +15,19 @@ set_system_mode: - "DayOff" - "HeatingOff" period: - name: Period - description: >- - A period of time in days; used only with Away, DayOff, or Custom. The system - will revert to Auto at midnight (up to 99 days, today is day 1). example: '{"days": 28}' selector: object: duration: - name: Duration - description: The duration in hours; used only with AutoWithEco (up to 24 hours). example: '{"hours": 18}' selector: object: reset_system: - name: Reset system - description: >- - Set the system to Auto mode and reset all the zones to follow their schedules. - Not all Evohome systems support this feature (i.e. AutoWithReset mode). - refresh_system: - name: Refresh system - description: >- - Pull the latest data from the vendor's servers now, rather than waiting for the - next scheduled update. - set_zone_override: - name: Set zone override - description: >- - Override a zone's setpoint, either indefinitely, or for a specified period of - time, after which it will revert to following its schedule. fields: entity_id: - name: Entity - description: The entity_id of the Evohome zone. required: true example: climate.bathroom selector: @@ -63,8 +35,6 @@ set_zone_override: integration: evohome domain: climate setpoint: - name: Setpoint - description: The temperature to be used instead of the scheduled setpoint. required: true selector: number: @@ -72,21 +42,13 @@ set_zone_override: max: 35.0 step: 0.1 duration: - name: Duration - description: >- - The zone will revert to its schedule after this time. If 0 the change is until - the next scheduled setpoint. example: '{"minutes": 135}' selector: object: clear_zone_override: - name: Clear zone override - description: Set a zone to follow its schedule. fields: entity_id: - name: Entity - description: The entity_id of the zone. required: true selector: entity: diff --git a/homeassistant/components/evohome/strings.json b/homeassistant/components/evohome/strings.json new file mode 100644 index 00000000000000..d8214c3aa8bf31 --- /dev/null +++ b/homeassistant/components/evohome/strings.json @@ -0,0 +1,58 @@ +{ + "services": { + "set_system_mode": { + "name": "Set system mode", + "description": "Sets the system mode, either indefinitely, or for a specified period of time, after which it will revert to Auto. Not all systems support all modes.", + "fields": { + "mode": { + "name": "Mode", + "description": "Mode to set thermostat." + }, + "period": { + "name": "Period", + "description": "A period of time in days; used only with Away, DayOff, or Custom. The system will revert to Auto at midnight (up to 99 days, today is day 1)." + }, + "duration": { + "name": "Duration", + "description": "The duration in hours; used only with AutoWithEco (up to 24 hours)." + } + } + }, + "reset_system": { + "name": "Reset system", + "description": "Sets the system to Auto mode and reset all the zones to follow their schedules. Not all Evohome systems support this feature (i.e. AutoWithReset mode)." + }, + "refresh_system": { + "name": "Refresh system", + "description": "Pulls the latest data from the vendor's servers now, rather than waiting for the next scheduled update." + }, + "set_zone_override": { + "name": "Set zone override", + "description": "Overrides a zone's setpoint, either indefinitely, or for a specified period of time, after which it will revert to following its schedule.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "The entity_id of the Evohome zone." + }, + "setpoint": { + "name": "Setpoint", + "description": "The temperature to be used instead of the scheduled setpoint." + }, + "duration": { + "name": "Duration", + "description": "The zone will revert to its schedule after this time. If 0 the change is until the next scheduled setpoint." + } + } + }, + "clear_zone_override": { + "name": "Clear zone override", + "description": "Sets a zone to follow its schedule.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "The entity_id of the zone." + } + } + } + } +} diff --git a/homeassistant/components/ezviz/services.yaml b/homeassistant/components/ezviz/services.yaml index 9733d7418a34e4..7d1cda2fa637a1 100644 --- a/homeassistant/components/ezviz/services.yaml +++ b/homeassistant/components/ezviz/services.yaml @@ -1,14 +1,10 @@ alarm_sound: - name: Set warning sound level. - description: Set movement warning sound level. target: entity: integration: ezviz domain: camera fields: level: - name: Sound level - description: Sound level (2 is disabled, 1 intensive, 0 soft). required: true example: 0 default: 0 @@ -19,16 +15,12 @@ alarm_sound: step: 1 mode: box ptz: - name: PTZ - description: Moves the camera to the direction, with defined speed target: entity: integration: ezviz domain: camera fields: direction: - name: Direction - description: Direction to move camera (up, down, left, right). required: true example: "up" default: "up" @@ -40,8 +32,6 @@ ptz: - "left" - "right" speed: - name: Speed - description: Speed of movement (from 1 to 9). required: true example: 5 default: 5 @@ -52,17 +42,12 @@ ptz: step: 1 mode: box set_alarm_detection_sensibility: - name: Detection sensitivity - description: Sets the detection sensibility level. target: entity: integration: ezviz domain: camera fields: level: - name: Sensitivity Level - description: "Sensibility level (1-6) for type 0 (Normal camera) - or (1-100) for type 3 (PIR sensor camera)." required: true example: 3 default: 3 @@ -73,8 +58,6 @@ set_alarm_detection_sensibility: step: 1 mode: box type_value: - name: Detection type - description: "Type of detection. Options : 0 - Camera or 3 - PIR Sensor Camera" required: true example: "0" default: "0" @@ -84,15 +67,12 @@ set_alarm_detection_sensibility: - "0" - "3" sound_alarm: - name: Sound Alarm - description: Sounds the alarm on your camera. target: entity: integration: ezviz domain: camera fields: enable: - description: Enter 1 or 2 (1=disable, 2=enable). required: true example: 1 default: 1 @@ -103,8 +83,6 @@ sound_alarm: step: 1 mode: box wake_device: - name: Wake Camera - description: This can be used to wake the camera/device from hibernation. target: entity: integration: ezviz diff --git a/homeassistant/components/ezviz/strings.json b/homeassistant/components/ezviz/strings.json index 92ff8c6fa05ed7..5355fcc377ca3a 100644 --- a/homeassistant/components/ezviz/strings.json +++ b/homeassistant/components/ezviz/strings.json @@ -71,5 +71,59 @@ } } } + }, + "services": { + "alarm_sound": { + "name": "Set warning sound level.", + "description": "Setx movement warning sound level.", + "fields": { + "level": { + "name": "Sound level", + "description": "Sound level (2 is disabled, 1 intensive, 0 soft)." + } + } + }, + "ptz": { + "name": "PTZ", + "description": "Moves the camera to the direction, with defined speed.", + "fields": { + "direction": { + "name": "Direction", + "description": "Direction to move camera (up, down, left, right)." + }, + "speed": { + "name": "Speed", + "description": "Speed of movement (from 1 to 9)." + } + } + }, + "set_alarm_detection_sensibility": { + "name": "Detection sensitivity", + "description": "Sets the detection sensibility level.", + "fields": { + "level": { + "name": "Sensitivity level", + "description": "Sensibility level (1-6) for type 0 (Normal camera) or (1-100) for type 3 (PIR sensor camera)." + }, + "type_value": { + "name": "Detection type", + "description": "Type of detection. Options : 0 - Camera or 3 - PIR Sensor Camera." + } + } + }, + "sound_alarm": { + "name": "Sound alarm", + "description": "Sounds the alarm on your camera.", + "fields": { + "enable": { + "name": "Alarm sound", + "description": "Enter 1 or 2 (1=disable, 2=enable)." + } + } + }, + "wake_device": { + "name": "Wake camera", + "description": "This can be used to wake the camera/device from hibernation." + } } } diff --git a/homeassistant/components/facebox/services.yaml b/homeassistant/components/facebox/services.yaml index 3f968cf385a8e2..0438338f55e1ef 100644 --- a/homeassistant/components/facebox/services.yaml +++ b/homeassistant/components/facebox/services.yaml @@ -1,24 +1,16 @@ teach_face: - name: Teach face - description: Teach facebox a face using a file. fields: entity_id: - name: Entity - description: The facebox entity to teach. selector: entity: integration: facebox domain: image_processing name: - name: Name - description: The name of the face to teach. required: true example: "my_name" selector: text: file_path: - name: File path - description: The path to the image file. required: true example: "/images/my_image.jpg" selector: diff --git a/homeassistant/components/facebox/strings.json b/homeassistant/components/facebox/strings.json new file mode 100644 index 00000000000000..776644c7cfa2f9 --- /dev/null +++ b/homeassistant/components/facebox/strings.json @@ -0,0 +1,22 @@ +{ + "services": { + "teach_face": { + "name": "Teach face", + "description": "Teaches facebox a face using a file.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "The facebox entity to teach." + }, + "name": { + "name": "Name", + "description": "The name of the face to teach." + }, + "file_path": { + "name": "File path", + "description": "The path to the image file." + } + } + } + } +} diff --git a/homeassistant/components/fastdotcom/services.yaml b/homeassistant/components/fastdotcom/services.yaml index 75963557a03a24..002b28b4e4d685 100644 --- a/homeassistant/components/fastdotcom/services.yaml +++ b/homeassistant/components/fastdotcom/services.yaml @@ -1,3 +1 @@ speedtest: - name: Speed test - description: Immediately execute a speed test with Fast.com diff --git a/homeassistant/components/fastdotcom/strings.json b/homeassistant/components/fastdotcom/strings.json new file mode 100644 index 00000000000000..b1e03681c960cc --- /dev/null +++ b/homeassistant/components/fastdotcom/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "speedtest": { + "name": "Speed test", + "description": "Immediately executs a speed test with Fast.com." + } + } +} diff --git a/homeassistant/components/ffmpeg/services.yaml b/homeassistant/components/ffmpeg/services.yaml index 1fdde46e55c46a..35c11ee678f28c 100644 --- a/homeassistant/components/ffmpeg/services.yaml +++ b/homeassistant/components/ffmpeg/services.yaml @@ -1,32 +1,20 @@ restart: - name: Restart - description: Send a restart command to a ffmpeg based sensor. fields: entity_id: - name: Entity - description: Name of entity that will restart. Platform dependent. selector: entity: integration: ffmpeg domain: binary_sensor start: - name: Start - description: Send a start command to a ffmpeg based sensor. fields: entity_id: - name: Entity - description: Name of entity that will start. Platform dependent. selector: entity: integration: ffmpeg domain: binary_sensor stop: - name: Stop - description: Send a stop command to a ffmpeg based sensor. fields: entity_id: - name: Entity - description: Name of entity that will stop. Platform dependent. selector: entity: integration: ffmpeg diff --git a/homeassistant/components/ffmpeg/strings.json b/homeassistant/components/ffmpeg/strings.json new file mode 100644 index 00000000000000..9aaff2d1e9343b --- /dev/null +++ b/homeassistant/components/ffmpeg/strings.json @@ -0,0 +1,34 @@ +{ + "services": { + "restart": { + "name": "Restart", + "description": "Sends a restart command to a ffmpeg based sensor.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name of entity that will restart. Platform dependent." + } + } + }, + "start": { + "name": "Start", + "description": "Sends a start command to a ffmpeg based sensor.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name of entity that will start. Platform dependent." + } + } + }, + "stop": { + "name": "Stop", + "description": "Sends a stop command to a ffmpeg based sensor.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name of entity that will stop. Platform dependent." + } + } + } + } +} diff --git a/homeassistant/components/flo/services.yaml b/homeassistant/components/flo/services.yaml index a074ebafe9996b..ce4abacb64cbac 100644 --- a/homeassistant/components/flo/services.yaml +++ b/homeassistant/components/flo/services.yaml @@ -1,16 +1,12 @@ # Describes the format for available Flo services set_sleep_mode: - name: Set sleep mode - description: Set the location into sleep mode. target: entity: integration: flo domain: switch fields: sleep_minutes: - name: Sleep minutes - description: The time to sleep in minutes. default: true selector: select: @@ -19,8 +15,6 @@ set_sleep_mode: - "1440" - "4320" revert_to_mode: - name: Revert to mode - description: The mode to revert to after sleep_minutes has elapsed. default: true selector: select: @@ -28,22 +22,16 @@ set_sleep_mode: - "away" - "home" set_away_mode: - name: Set away mode - description: Set the location into away mode. target: entity: integration: flo domain: switch set_home_mode: - name: Set home mode - description: Set the location into home mode. target: entity: integration: flo domain: switch run_health_test: - name: Run health test - description: Have the Flo device run a health test. target: entity: integration: flo diff --git a/homeassistant/components/flo/strings.json b/homeassistant/components/flo/strings.json index fadfc304fce415..627f562be7e14c 100644 --- a/homeassistant/components/flo/strings.json +++ b/homeassistant/components/flo/strings.json @@ -49,5 +49,33 @@ "name": "Shutoff valve" } } + }, + "services": { + "set_sleep_mode": { + "name": "Set sleep mode", + "description": "Sets the location into sleep mode.", + "fields": { + "sleep_minutes": { + "name": "Sleep minutes", + "description": "The time to sleep in minutes." + }, + "revert_to_mode": { + "name": "Revert to mode", + "description": "The mode to revert to after sleep_minutes has elapsed." + } + } + }, + "set_away_mode": { + "name": "Set away mode", + "description": "Sets the location into away mode." + }, + "set_home_mode": { + "name": "Set home mode", + "description": "Sets the location into home mode." + }, + "run_health_test": { + "name": "Run health test", + "description": "Have the Flo device run a health test." + } } } diff --git a/homeassistant/components/flux_led/services.yaml b/homeassistant/components/flux_led/services.yaml index 5d880370818bb2..73f479825da4c0 100644 --- a/homeassistant/components/flux_led/services.yaml +++ b/homeassistant/components/flux_led/services.yaml @@ -1,13 +1,10 @@ set_custom_effect: - name: Set custom effect - description: Set a custom light effect. target: entity: integration: flux_led domain: light fields: colors: - description: List of colors for the custom effect (RGB). (Max 16 Colors) example: | - [255,0,0] - [0,255,0] @@ -16,7 +13,6 @@ set_custom_effect: selector: object: speed_pct: - description: Effect speed for the custom effect (0-100). example: 80 default: 50 required: false @@ -27,7 +23,6 @@ set_custom_effect: max: 100 unit_of_measurement: "%" transition: - description: Effect transition. example: "jump" default: "gradual" required: false @@ -38,15 +33,12 @@ set_custom_effect: - "jump" - "strobe" set_zones: - name: Set zones - description: Set strip zones for Addressable v3 controllers (0xA3). target: entity: integration: flux_led domain: light fields: colors: - description: List of colors for each zone (RGB). The length of each zone is the number of pixels per segment divided by the number of colors. (Max 2048 Colors) example: | - [255,0,0] - [0,255,0] @@ -56,7 +48,6 @@ set_zones: selector: object: speed_pct: - description: Effect speed for the custom effect (0-100) example: 80 default: 50 required: false @@ -67,7 +58,6 @@ set_zones: max: 100 unit_of_measurement: "%" effect: - description: Effect example: "running_water" default: "static" required: false @@ -80,15 +70,12 @@ set_zones: - "jump" - "breathing" set_music_mode: - name: Set music mode - description: Configure music mode on Controller RGB with MIC (0x08), Addressable v2 (0xA2), and Addressable v3 (0xA3) devices that have a built-in microphone. target: entity: integration: flux_led domain: light fields: sensitivity: - description: Microphone sensitivity (0-100) example: 80 default: 100 required: false @@ -99,7 +86,6 @@ set_music_mode: max: 100 unit_of_measurement: "%" brightness: - description: Light brightness (0-100) example: 80 default: 100 required: false @@ -110,13 +96,11 @@ set_music_mode: max: 100 unit_of_measurement: "%" light_screen: - description: Light screen mode for 2 dimensional pixels (Addressable models only) default: false required: false selector: boolean: effect: - description: Effect (1-16 on Addressable models, 0-3 on RGB with MIC models) example: 1 default: 1 required: false @@ -126,13 +110,11 @@ set_music_mode: step: 1 max: 16 foreground_color: - description: The foreground RGB color example: "[255, 100, 100]" required: false selector: object: background_color: - description: The background RGB color (Addressable models only) example: "[255, 100, 100]" required: false selector: diff --git a/homeassistant/components/flux_led/strings.json b/homeassistant/components/flux_led/strings.json index 51edd207e95073..7617d56d512194 100644 --- a/homeassistant/components/flux_led/strings.json +++ b/homeassistant/components/flux_led/strings.json @@ -89,5 +89,73 @@ "name": "Music" } } + }, + "services": { + "set_custom_effect": { + "name": "Set custom effect", + "description": "Sets a custom light effect.", + "fields": { + "colors": { + "name": "Colors", + "description": "List of colors for the custom effect (RGB). (Max 16 Colors)." + }, + "speed_pct": { + "name": "Speed", + "description": "Effect speed for the custom effect (0-100)." + }, + "transition": { + "name": "Transition", + "description": "Effect transition." + } + } + }, + "set_zones": { + "name": "Set zones", + "description": "Sets strip zones for Addressable v3 controllers (0xA3).", + "fields": { + "colors": { + "name": "Colors", + "description": "List of colors for each zone (RGB). The length of each zone is the number of pixels per segment divided by the number of colors. (Max 2048 Colors)." + }, + "speed_pct": { + "name": "Speed", + "description": "Effect speed for the custom effect (0-100)." + }, + "effect": { + "name": "Effect", + "description": "Effect." + } + } + }, + "set_music_mode": { + "name": "Set music mode", + "description": "Configures music mode on Controller RGB with MIC (0x08), Addressable v2 (0xA2), and Addressable v3 (0xA3) devices that have a built-in microphone.", + "fields": { + "sensitivity": { + "name": "Sensitivity", + "description": "Microphone sensitivity (0-100)." + }, + "brightness": { + "name": "Brightness", + "description": "Light brightness (0-100)." + }, + "light_screen": { + "name": "Light screen", + "description": "Light screen mode for 2 dimensional pixels (Addressable models only)." + }, + "effect": { + "name": "Effect", + "description": "Effect (1-16 on Addressable models, 0-3 on RGB with MIC models)." + }, + "foreground_color": { + "name": "Foreground color", + "description": "The foreground RGB color." + }, + "background_color": { + "name": "Background color", + "description": "The background RGB color (Addressable models only)." + } + } + } } } diff --git a/homeassistant/components/foscam/services.yaml b/homeassistant/components/foscam/services.yaml index a7e5394802bbdc..ad46ec130d0386 100644 --- a/homeassistant/components/foscam/services.yaml +++ b/homeassistant/components/foscam/services.yaml @@ -1,13 +1,10 @@ ptz: - name: PTZ - description: Pan/Tilt service for Foscam camera. target: entity: integration: foscam domain: camera fields: movement: - description: "Direction of the movement." required: true selector: select: @@ -21,7 +18,6 @@ ptz: - "top_right" - "up" travel_time: - description: "Travel time in seconds." default: 0.125 selector: number: @@ -31,15 +27,12 @@ ptz: unit_of_measurement: seconds ptz_preset: - name: PTZ preset - description: PTZ Preset service for Foscam camera. target: entity: integration: foscam domain: camera fields: preset_name: - description: "The name of the preset to move to. Presets can be created from within the official Foscam apps." required: true example: "TopMost" selector: diff --git a/homeassistant/components/foscam/strings.json b/homeassistant/components/foscam/strings.json index 14aa88b79526e6..35964ee4546ce9 100644 --- a/homeassistant/components/foscam/strings.json +++ b/homeassistant/components/foscam/strings.json @@ -21,5 +21,31 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" } + }, + "services": { + "ptz": { + "name": "PTZ", + "description": "Pan/Tilt service for Foscam camera.", + "fields": { + "movement": { + "name": "Movement", + "description": "Direction of the movement." + }, + "travel_time": { + "name": "Travel time", + "description": "Travel time in seconds." + } + } + }, + "ptz_preset": { + "name": "PTZ preset", + "description": "PTZ Preset service for Foscam camera.", + "fields": { + "preset_name": { + "name": "Preset name", + "description": "The name of the preset to move to. Presets can be created from within the official Foscam apps." + } + } + } } } diff --git a/homeassistant/components/freebox/services.yaml b/homeassistant/components/freebox/services.yaml index 7b2a4059434aeb..8ba6f278bfa8e8 100644 --- a/homeassistant/components/freebox/services.yaml +++ b/homeassistant/components/freebox/services.yaml @@ -1,5 +1,3 @@ # Freebox service entries description. reboot: - name: Reboot - description: Reboots the Freebox. diff --git a/homeassistant/components/freebox/strings.json b/homeassistant/components/freebox/strings.json index 53a5fd59de3b0a..5c4143b4562ac8 100644 --- a/homeassistant/components/freebox/strings.json +++ b/homeassistant/components/freebox/strings.json @@ -20,5 +20,11 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" } + }, + "services": { + "reboot": { + "name": "Reboot", + "description": "Reboots the Freebox." + } } } diff --git a/homeassistant/components/fritz/services.yaml b/homeassistant/components/fritz/services.yaml index 95527257ea9c48..b9828280aa2ac9 100644 --- a/homeassistant/components/fritz/services.yaml +++ b/homeassistant/components/fritz/services.yaml @@ -1,10 +1,6 @@ reconnect: - name: Reconnect - description: Reconnects your FRITZ!Box internet connection fields: device_id: - name: Fritz!Box Device - description: Select the Fritz!Box to reconnect required: true selector: device: @@ -12,12 +8,8 @@ reconnect: entity: device_class: connectivity reboot: - name: Reboot - description: Reboots your FRITZ!Box fields: device_id: - name: Fritz!Box Device - description: Select the Fritz!Box to reboot required: true selector: device: @@ -26,12 +18,8 @@ reboot: device_class: connectivity cleanup: - name: Remove stale device tracker entities - description: Remove FRITZ!Box stale device_tracker entities fields: device_id: - name: Fritz!Box Device - description: Select the Fritz!Box to check required: true selector: device: @@ -39,12 +27,8 @@ cleanup: entity: device_class: connectivity set_guest_wifi_password: - name: Set guest wifi password - description: Set a new password for the guest wifi. The password must be between 8 and 63 characters long. If no additional parameter is set, the password will be auto-generated with a length of 12 characters. fields: device_id: - name: Fritz!Box Device - description: Select the Fritz!Box to check required: true selector: device: @@ -52,14 +36,10 @@ set_guest_wifi_password: entity: device_class: connectivity password: - name: Password - description: New password for the guest wifi required: false selector: text: length: - name: Password length - description: Length of the new password. The password will be auto-generated, if no password is set. required: false selector: number: diff --git a/homeassistant/components/fritz/strings.json b/homeassistant/components/fritz/strings.json index fcaa56424f1b65..dd845fc2a1b54e 100644 --- a/homeassistant/components/fritz/strings.json +++ b/homeassistant/components/fritz/strings.json @@ -55,33 +55,123 @@ }, "entity": { "binary_sensor": { - "is_connected": { "name": "Connection" }, - "is_linked": { "name": "Link" } + "is_connected": { + "name": "Connection" + }, + "is_linked": { + "name": "Link" + } }, "button": { - "cleanup": { "name": "Cleanup" }, - "firmware_update": { "name": "Firmware update" }, - "reconnect": { "name": "Reconnect" } + "cleanup": { + "name": "Cleanup" + }, + "firmware_update": { + "name": "Firmware update" + }, + "reconnect": { + "name": "Reconnect" + } }, "sensor": { - "connection_uptime": { "name": "Connection uptime" }, - "device_uptime": { "name": "Last restart" }, - "external_ip": { "name": "External IP" }, - "external_ipv6": { "name": "External IPv6" }, - "gb_received": { "name": "GB received" }, - "gb_sent": { "name": "GB sent" }, - "kb_s_received": { "name": "Download throughput" }, - "kb_s_sent": { "name": "Upload throughput" }, + "connection_uptime": { + "name": "Connection uptime" + }, + "device_uptime": { + "name": "Last restart" + }, + "external_ip": { + "name": "External IP" + }, + "external_ipv6": { + "name": "External IPv6" + }, + "gb_received": { + "name": "GB received" + }, + "gb_sent": { + "name": "GB sent" + }, + "kb_s_received": { + "name": "Download throughput" + }, + "kb_s_sent": { + "name": "Upload throughput" + }, "link_attenuation_received": { "name": "Link download power attenuation" }, - "link_attenuation_sent": { "name": "Link upload power attenuation" }, - "link_kb_s_received": { "name": "Link download throughput" }, - "link_kb_s_sent": { "name": "Link upload throughput" }, - "link_noise_margin_received": { "name": "Link download noise margin" }, - "link_noise_margin_sent": { "name": "Link upload noise margin" }, - "max_kb_s_received": { "name": "Max connection download throughput" }, - "max_kb_s_sent": { "name": "Max connection upload throughput" } + "link_attenuation_sent": { + "name": "Link upload power attenuation" + }, + "link_kb_s_received": { + "name": "Link download throughput" + }, + "link_kb_s_sent": { + "name": "Link upload throughput" + }, + "link_noise_margin_received": { + "name": "Link download noise margin" + }, + "link_noise_margin_sent": { + "name": "Link upload noise margin" + }, + "max_kb_s_received": { + "name": "Max connection download throughput" + }, + "max_kb_s_sent": { + "name": "Max connection upload throughput" + } + } + }, + "services": { + "reconnect": { + "name": "Reconnect", + "description": "Reconnects your FRITZ!Box internet connection.", + "fields": { + "device_id": { + "name": "Fritz!Box Device", + "description": "Select the Fritz!Box to reconnect." + } + } + }, + "reboot": { + "name": "Reboot", + "description": "Reboots your FRITZ!Box.", + "fields": { + "device_id": { + "name": "Fritz!Box Device", + "description": "Select the Fritz!Box to reboot." + } + } + }, + "cleanup": { + "name": "Remove stale device tracker entities", + "description": "Remove FRITZ!Box stale device_tracker entities.", + "fields": { + "device_id": { + "name": "Fritz!Box Device", + "description": "Select the Fritz!Box to check." + } + } + }, + "set_guest_wifi_password": { + "name": "Set guest Wi-Fi password", + "description": "Sets a new password for the guest Wi-Fi. The password must be between 8 and 63 characters long. If no additional parameter is set, the password will be auto-generated with a length of 12 characters.", + "fields": { + "device_id": { + "name": "Fritz!Box Device", + "description": "Select the Fritz!Box to check." + }, + "password": { + "name": "Password", + "description": "New password for the guest Wi-Fi." + }, + "length": { + "name": "Password length", + "description": "Length of the new password. The password will be auto-generated, if no password is set." + } + } } } } diff --git a/homeassistant/components/fully_kiosk/services.yaml b/homeassistant/components/fully_kiosk/services.yaml index 1f75e4a0347368..7784996da9beb5 100644 --- a/homeassistant/components/fully_kiosk/services.yaml +++ b/homeassistant/components/fully_kiosk/services.yaml @@ -1,50 +1,36 @@ load_url: - name: Load URL - description: Load a URL on Fully Kiosk Browser target: device: integration: fully_kiosk fields: url: - name: URL - description: URL to load. example: "https://home-assistant.io" required: true selector: text: set_config: - name: Set Configuration - description: Set a configuration parameter on Fully Kiosk Browser. target: device: integration: fully_kiosk fields: key: - name: Key - description: Configuration parameter to set. example: "motionSensitivity" required: true selector: text: value: - name: Value - description: Value for the configuration parameter. example: "90" required: true selector: text: start_application: - name: Start Application - description: Start an application on the device running Fully Kiosk Browser. target: device: integration: fully_kiosk fields: application: - name: Application - description: Package name of the application to start. example: "de.ozerov.fully" required: true selector: diff --git a/homeassistant/components/fully_kiosk/strings.json b/homeassistant/components/fully_kiosk/strings.json index c10b6162859a08..2ecac4a57422ea 100644 --- a/homeassistant/components/fully_kiosk/strings.json +++ b/homeassistant/components/fully_kiosk/strings.json @@ -105,5 +105,41 @@ "name": "Screen" } } + }, + "services": { + "load_url": { + "name": "Load URL", + "description": "Loads a URL on Fully Kiosk Browser.", + "fields": { + "url": { + "name": "URL", + "description": "URL to load." + } + } + }, + "set_config": { + "name": "Set Configuration", + "description": "Sets a configuration parameter on Fully Kiosk Browser.", + "fields": { + "key": { + "name": "Key", + "description": "Configuration parameter to set." + }, + "value": { + "name": "Value", + "description": "Value for the configuration parameter." + } + } + }, + "start_application": { + "name": "Start Application", + "description": "Starts an application on the device running Fully Kiosk Browser.", + "fields": { + "application": { + "name": "Application", + "description": "Package name of the application to start." + } + } + } } } From 0329378f2f4db151cd39704053a83e88f6fcb452 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 00:24:16 +0200 Subject: [PATCH 063/154] Migrate integration services (L-M) to support translations (#96374) --- homeassistant/components/lcn/services.yaml | 114 -------- homeassistant/components/lcn/strings.json | 256 ++++++++++++++++++ homeassistant/components/lifx/services.yaml | 80 ------ homeassistant/components/lifx/strings.json | 176 ++++++++++++ .../components/litterrobot/services.yaml | 6 - .../components/litterrobot/strings.json | 16 ++ .../components/local_file/services.yaml | 6 - .../components/local_file/strings.json | 18 ++ .../components/logi_circle/services.yaml | 22 -- .../components/logi_circle/strings.json | 56 +++- homeassistant/components/lyric/services.yaml | 4 - homeassistant/components/lyric/strings.json | 12 + homeassistant/components/matrix/services.yaml | 8 - homeassistant/components/matrix/strings.json | 22 ++ homeassistant/components/mazda/services.yaml | 10 - homeassistant/components/mazda/strings.json | 24 ++ .../components/media_extractor/services.yaml | 6 - .../components/media_extractor/strings.json | 18 ++ .../components/melcloud/services.yaml | 12 - .../components/melcloud/strings.json | 22 ++ .../components/microsoft_face/services.yaml | 32 --- .../components/microsoft_face/strings.json | 80 ++++++ homeassistant/components/mill/services.yaml | 10 - homeassistant/components/mill/strings.json | 24 ++ homeassistant/components/minio/services.yaml | 22 -- homeassistant/components/minio/strings.json | 54 ++++ homeassistant/components/modbus/services.yaml | 30 -- homeassistant/components/modbus/strings.json | 72 +++++ .../components/modern_forms/services.yaml | 12 - .../components/modern_forms/strings.json | 30 ++ .../components/monoprice/services.yaml | 4 - .../components/monoprice/strings.json | 10 + .../components/motion_blinds/services.yaml | 8 - .../components/motion_blinds/strings.json | 20 ++ .../components/motioneye/services.yaml | 16 -- .../components/motioneye/strings.json | 38 +++ 36 files changed, 947 insertions(+), 403 deletions(-) create mode 100644 homeassistant/components/local_file/strings.json create mode 100644 homeassistant/components/matrix/strings.json create mode 100644 homeassistant/components/media_extractor/strings.json create mode 100644 homeassistant/components/microsoft_face/strings.json create mode 100644 homeassistant/components/minio/strings.json create mode 100644 homeassistant/components/modbus/strings.json diff --git a/homeassistant/components/lcn/services.yaml b/homeassistant/components/lcn/services.yaml index 52aa886387230e..d62a1e72d45209 100644 --- a/homeassistant/components/lcn/services.yaml +++ b/homeassistant/components/lcn/services.yaml @@ -1,19 +1,13 @@ # Describes the format for available LCN services output_abs: - name: Output absolute brightness - description: Set absolute brightness of output port in percent. fields: address: - name: Address - description: Module address required: true example: "myhome.s0.m7" selector: text: output: - name: Output - description: Output port required: true selector: select: @@ -23,8 +17,6 @@ output_abs: - "output3" - "output4" brightness: - name: Brightness - description: Absolute brightness. required: true selector: number: @@ -32,8 +24,6 @@ output_abs: max: 100 unit_of_measurement: "%" transition: - name: Transition - description: Transition time. default: 0 selector: number: @@ -43,19 +33,13 @@ output_abs: unit_of_measurement: seconds output_rel: - name: Output relative brightness - description: Set relative brightness of output port in percent. fields: address: - name: Address - description: Module address required: true example: "myhome.s0.m7" selector: text: output: - name: Output - description: Output port required: true selector: select: @@ -65,8 +49,6 @@ output_rel: - "output3" - "output4" brightness: - name: Brightness - description: Relative brightness. required: true selector: number: @@ -75,19 +57,13 @@ output_rel: unit_of_measurement: "%" output_toggle: - name: Toggle output - description: Toggle output port. fields: address: - name: Address - description: Module address required: true example: "myhome.s0.m7" selector: text: output: - name: Output - description: Output port required: true selector: select: @@ -97,8 +73,6 @@ output_toggle: - "output3" - "output4" transition: - name: Transition - description: Transition time. default: 0 selector: number: @@ -108,38 +82,26 @@ output_toggle: unit_of_measurement: seconds relays: - name: Relays - description: Set the relays status. fields: address: - name: Address - description: Module address required: true example: "myhome.s0.m7" selector: text: state: - name: State - description: Relays states as string (1=on, 2=off, t=toggle, -=no change) required: true example: "t---001-" selector: text: led: - name: LED - description: Set the led state. fields: address: - name: Address - description: Module address required: true example: "myhome.s0.m7" selector: text: led: - name: LED - description: Led required: true selector: select: @@ -157,8 +119,6 @@ led: - "led11" - "led12" state: - name: State - description: Led state required: true selector: select: @@ -169,19 +129,13 @@ led: - "on" var_abs: - name: Set absolute variable - description: Set absolute value of a variable or setpoint. fields: address: - name: Address - description: Module address required: true example: "myhome.s0.m7" selector: text: variable: - name: Variable - description: Variable or setpoint name required: true default: native selector: @@ -208,16 +162,12 @@ var_abs: - "var11" - "var12" value: - name: Value - description: Value to set. default: 0 selector: number: min: 0 max: 100000 unit_of_measurement: - name: Unit of measurement - description: Unit of value. selector: select: options: @@ -246,19 +196,13 @@ var_abs: - "volt" var_reset: - name: Reset variable - description: Reset value of variable or setpoint. fields: address: - name: Address - description: Module address required: true example: "myhome.s0.m7" selector: text: variable: - name: Variable - description: Variable or setpoint name. required: true selector: select: @@ -285,19 +229,13 @@ var_reset: - "var12" var_rel: - name: Shift variable - description: Shift value of a variable, setpoint or threshold. fields: address: - name: Address - description: Module address required: true example: "myhome.s0.m7" selector: text: variable: - name: Variable - description: Variable or setpoint name required: true selector: select: @@ -340,16 +278,12 @@ var_rel: - "var11" - "var12" value: - name: Value - description: Shift value default: 0 selector: number: min: 0 max: 100000 unit_of_measurement: - name: Unit of measurement - description: Unit of value default: native selector: select: @@ -378,8 +312,6 @@ var_rel: - "v" - "volt" value_reference: - name: Reference value - description: Reference value for setpoint and threshold default: current selector: select: @@ -388,19 +320,13 @@ var_rel: - "prog" lock_regulator: - name: Lock regulator - description: Lock a regulator setpoint. fields: address: - name: Address - description: Module address required: true example: "myhome.s0.m7" selector: text: setpoint: - name: Setpoint - description: Setpoint name required: true selector: select: @@ -423,33 +349,23 @@ lock_regulator: - "thrs4_3" - "thrs4_4" state: - name: State - description: New setpoint state default: false selector: boolean: send_keys: - name: Send keys - description: Send keys (which executes bound commands). fields: address: - name: Address - description: Module address required: true example: "myhome.s0.m7" selector: text: keys: - name: Keys - description: Keys to send required: true example: "a1a5d8" selector: text: state: - name: State - description: "Key state upon sending (must be hit for deferred)" default: hit selector: select: @@ -459,16 +375,12 @@ send_keys: - "break" - "dontsend" time: - name: Time - description: Send delay. default: 0 selector: number: min: 0 max: 60 time_unit: - name: Time unit - description: Time unit of send delay. default: s selector: select: @@ -489,41 +401,29 @@ send_keys: - "seconds" lock_keys: - name: Lock keys - description: Lock keys. fields: address: - name: Address - description: Module address required: true example: "myhome.s0.m7" selector: text: table: - name: Table - description: "Table with keys to lock (must be A for interval)." example: "a" default: a selector: text: state: - name: State - description: Key lock states as string (1=on, 2=off, T=toggle, -=nochange) required: true example: "1---t0--" selector: text: time: - name: Time - description: Lock interval. default: 0 selector: number: min: 0 max: 60 time_unit: - name: Time unit - description: Time unit of lock interval. default: s selector: select: @@ -544,46 +444,32 @@ lock_keys: - "seconds" dyn_text: - name: Dynamic text - description: Send dynamic text to LCN-GTxD displays. fields: address: - name: Address - description: Module address required: true example: "myhome.s0.m7" selector: text: row: - name: Row - description: Text row. required: true selector: number: min: 1 max: 4 text: - name: Text - description: Text to send (up to 60 characters encoded as UTF-8) required: true example: "text up to 60 characters" selector: text: pck: - name: PCK - description: Send arbitrary PCK command. fields: address: - name: Address - description: Module address required: true example: "myhome.s0.m7" selector: text: pck: - name: PCK - description: PCK command (without address header) required: true example: "PIN4" selector: diff --git a/homeassistant/components/lcn/strings.json b/homeassistant/components/lcn/strings.json index bee6c0f0e298b5..267100eaad631d 100644 --- a/homeassistant/components/lcn/strings.json +++ b/homeassistant/components/lcn/strings.json @@ -7,5 +7,261 @@ "codelock": "Code lock code received", "send_keys": "Send keys received" } + }, + "services": { + "output_abs": { + "name": "Output absolute brightness", + "description": "Sets absolute brightness of output port in percent.", + "fields": { + "address": { + "name": "Address", + "description": "Module address." + }, + "output": { + "name": "Output", + "description": "Output port." + }, + "brightness": { + "name": "Brightness", + "description": "Absolute brightness." + }, + "transition": { + "name": "Transition", + "description": "Transition time." + } + } + }, + "output_rel": { + "name": "Output relative brightness", + "description": "Sets relative brightness of output port in percent.", + "fields": { + "address": { + "name": "Address", + "description": "Module address." + }, + "output": { + "name": "Output", + "description": "Output port." + }, + "brightness": { + "name": "Brightness", + "description": "Relative brightness." + } + } + }, + "output_toggle": { + "name": "Toggle output", + "description": "Toggles output port.", + "fields": { + "address": { + "name": "Address", + "description": "Module address." + }, + "output": { + "name": "Output", + "description": "Output port." + }, + "transition": { + "name": "Transition", + "description": "Transition time." + } + } + }, + "relays": { + "name": "Relays", + "description": "Sets the relays status.", + "fields": { + "address": { + "name": "Address", + "description": "Module address." + }, + "state": { + "name": "State", + "description": "Relays states as string (1=on, 2=off, t=toggle, -=no change)." + } + } + }, + "led": { + "name": "LED", + "description": "Sets the led state.", + "fields": { + "address": { + "name": "Address", + "description": "Module address." + }, + "led": { + "name": "LED", + "description": "Led." + }, + "state": { + "name": "State", + "description": "Led state." + } + } + }, + "var_abs": { + "name": "Set absolute variable", + "description": "Sets absolute value of a variable or setpoint.", + "fields": { + "address": { + "name": "Address", + "description": "Module address." + }, + "variable": { + "name": "Variable", + "description": "Variable or setpoint name." + }, + "value": { + "name": "Value", + "description": "Value to set." + }, + "unit_of_measurement": { + "name": "Unit of measurement", + "description": "Unit of value." + } + } + }, + "var_reset": { + "name": "Reset variable", + "description": "Resets value of variable or setpoint.", + "fields": { + "address": { + "name": "Address", + "description": "Module address." + }, + "variable": { + "name": "Variable", + "description": "Variable or setpoint name." + } + } + }, + "var_rel": { + "name": "Shift variable", + "description": "Shift value of a variable, setpoint or threshold.", + "fields": { + "address": { + "name": "Address", + "description": "Module address." + }, + "variable": { + "name": "Variable", + "description": "Variable or setpoint name." + }, + "value": { + "name": "Value", + "description": "Shift value." + }, + "unit_of_measurement": { + "name": "Unit of measurement", + "description": "Unit of value." + }, + "value_reference": { + "name": "Reference value", + "description": "Reference value for setpoint and threshold." + } + } + }, + "lock_regulator": { + "name": "Lock regulator", + "description": "Locks a regulator setpoint.", + "fields": { + "address": { + "name": "Address", + "description": "Module address." + }, + "setpoint": { + "name": "Setpoint", + "description": "Setpoint name." + }, + "state": { + "name": "State", + "description": "New setpoint state." + } + } + }, + "send_keys": { + "name": "Send keys", + "description": "Sends keys (which executes bound commands).", + "fields": { + "address": { + "name": "Address", + "description": "Module address." + }, + "keys": { + "name": "Keys", + "description": "Keys to send." + }, + "state": { + "name": "State", + "description": "Key state upon sending (must be hit for deferred)." + }, + "time": { + "name": "Time", + "description": "Send delay." + }, + "time_unit": { + "name": "Time unit", + "description": "Time unit of send delay." + } + } + }, + "lock_keys": { + "name": "Lock keys", + "description": "Locks keys.", + "fields": { + "address": { + "name": "Address", + "description": "Module address." + }, + "table": { + "name": "Table", + "description": "Table with keys to lock (must be A for interval)." + }, + "state": { + "name": "State", + "description": "Key lock states as string (1=on, 2=off, T=toggle, -=nochange)." + }, + "time": { + "name": "Time", + "description": "Lock interval." + }, + "time_unit": { + "name": "Time unit", + "description": "Time unit of lock interval." + } + } + }, + "dyn_text": { + "name": "Dynamic text", + "description": "Sends dynamic text to LCN-GTxD displays.", + "fields": { + "address": { + "name": "Address", + "description": "Module address." + }, + "row": { + "name": "Row", + "description": "Text row." + }, + "text": { + "name": "Text", + "description": "Text to send (up to 60 characters encoded as UTF-8)." + } + } + }, + "pck": { + "name": "PCK", + "description": "Sends arbitrary PCK command.", + "fields": { + "address": { + "name": "Address", + "description": "Module address." + }, + "pck": { + "name": "PCK", + "description": "PCK command (without address header)." + } + } + } } } diff --git a/homeassistant/components/lifx/services.yaml b/homeassistant/components/lifx/services.yaml index 6613bb6a329e53..83d314396661ee 100644 --- a/homeassistant/components/lifx/services.yaml +++ b/homeassistant/components/lifx/services.yaml @@ -1,21 +1,15 @@ set_hev_cycle_state: - name: Set HEV cycle state - description: Control the HEV LEDs on a LIFX Clean bulb. target: entity: integration: lifx domain: light fields: power: - name: enable - description: Start or stop a Clean cycle. required: true example: true selector: boolean: duration: - name: Duration - description: How long the HEV LEDs will remain on. Uses the configured default duration if not specified. required: false default: 7200 example: 3600 @@ -25,51 +19,37 @@ set_hev_cycle_state: max: 86400 unit_of_measurement: seconds set_state: - name: Set State - description: Set a color/brightness and possibly turn the light on/off. target: entity: integration: lifx domain: light fields: infrared: - name: infrared - description: Automatic infrared level when light brightness is low. selector: number: min: 0 max: 255 zones: - name: Zones - description: List of zone numbers to affect (8 per LIFX Z, starts at 0). example: "[0,5]" selector: object: transition: - name: Transition - description: Duration it takes to get to the final state. selector: number: min: 0 max: 3600 unit_of_measurement: seconds power: - name: Power - description: Turn the light on or off. Leave out to keep the power as it is. selector: boolean: effect_pulse: - name: Pulse effect - description: Run a flash effect by changing to a color and back. target: entity: integration: lifx domain: light fields: mode: - name: Mode - description: "Decides how colors are changed." selector: select: options: @@ -79,35 +59,25 @@ effect_pulse: - "strobe" - "solid" brightness: - name: Brightness value - description: Number indicating brightness of the temporary color, where 1 is the minimum brightness and 255 is the maximum brightness supported by the light. selector: number: min: 1 max: 255 brightness_pct: - name: Brightness - description: Percentage indicating the brightness of the temporary color, where 1 is the minimum brightness and 100 is the maximum brightness supported by the light. selector: number: min: 1 max: 100 unit_of_measurement: "%" color_name: - name: Color name - description: A human readable color name. example: "red" selector: text: rgb_color: - name: RGB color - description: The temporary color in RGB-format. example: "[255, 100, 100]" selector: object: period: - name: Period - description: Duration of the effect. default: 1.0 selector: number: @@ -116,46 +86,34 @@ effect_pulse: step: 0.05 unit_of_measurement: seconds cycles: - name: Cycles - description: Number of times the effect should run. default: 1 selector: number: min: 1 max: 10000 power_on: - name: Power on - description: Powered off lights are temporarily turned on during the effect. default: true selector: boolean: effect_colorloop: - name: Color loop effect - description: Run an effect with looping colors. target: entity: integration: lifx domain: light fields: brightness: - name: Brightness value - description: Number indicating brightness of the color loop, where 1 is the minimum brightness and 255 is the maximum brightness supported by the light. selector: number: min: 0 max: 255 brightness_pct: - name: Brightness - description: Percentage indicating the brightness of the color loop, where 1 is the minimum brightness and 100 is the maximum brightness supported by the light. selector: number: min: 0 max: 100 unit_of_measurement: "%" saturation_min: - name: Minimum saturation - description: Percentage indicating the minimum saturation of the colors in the loop. default: 80 selector: number: @@ -163,8 +121,6 @@ effect_colorloop: max: 100 unit_of_measurement: "%" saturation_max: - name: Maximum saturation - description: Percentage indicating the maximum saturation of the colors in the loop. default: 100 selector: number: @@ -172,8 +128,6 @@ effect_colorloop: max: 100 unit_of_measurement: "%" period: - name: Period - description: Duration between color changes. default: 60 selector: number: @@ -182,8 +136,6 @@ effect_colorloop: step: 0.05 unit_of_measurement: seconds change: - name: Change - description: Hue movement per period, in degrees on a color wheel. default: 20 selector: number: @@ -191,8 +143,6 @@ effect_colorloop: max: 360 unit_of_measurement: "°" spread: - name: Spread - description: Maximum hue difference between participating lights, in degrees on a color wheel. default: 30 selector: number: @@ -200,22 +150,16 @@ effect_colorloop: max: 360 unit_of_measurement: "°" power_on: - name: Power on - description: Powered off lights are temporarily turned on during the effect. default: true selector: boolean: effect_move: - name: Move effect - description: Start the firmware-based Move effect on a LIFX Z, Lightstrip or Beam. target: entity: integration: lifx domain: light fields: speed: - name: Speed - description: How long in seconds for the effect to move across the length of the light. default: 3.0 example: 3.0 selector: @@ -225,8 +169,6 @@ effect_move: step: 0.1 unit_of_measurement: seconds direction: - name: Direction - description: Direction the effect will move across the device. default: right example: right selector: @@ -236,8 +178,6 @@ effect_move: - right - left theme: - name: Theme - description: (Optional) set one of the predefined themes onto the device before starting the effect. example: exciting default: exciting selector: @@ -269,22 +209,16 @@ effect_move: - "tranquil" - "warming" power_on: - name: Power on - description: Powered off lights will be turned on before starting the effect. default: true selector: boolean: effect_flame: - name: Flame effect - description: Start the firmware-based Flame effect on LIFX Tiles or Candle. target: entity: integration: lifx domain: light fields: speed: - name: Speed - description: How fast the flames will move. default: 3 selector: number: @@ -293,22 +227,16 @@ effect_flame: step: 1 unit_of_measurement: seconds power_on: - name: Power on - description: Powered off lights will be turned on before starting the effect. default: true selector: boolean: effect_morph: - name: Morph effect - description: Start the firmware-based Morph effect on LIFX Tiles on Candle. target: entity: integration: lifx domain: light fields: speed: - name: Speed - description: How fast the colors will move. default: 3 selector: number: @@ -317,15 +245,11 @@ effect_morph: step: 1 unit_of_measurement: seconds palette: - name: Palette - description: List of at least 2 and at most 16 colors as hue (0-360), saturation (0-100), brightness (0-100) and kelvin (1500-900) values to use for this effect. Overrides the theme attribute. example: - "[[0, 100, 100, 3500], [60, 100, 100, 3500]]" selector: object: theme: - name: Theme - description: Predefined color theme to use for the effect. Overridden by the palette attribute. selector: select: options: @@ -354,14 +278,10 @@ effect_morph: - "tranquil" - "warming" power_on: - name: Power on - description: Powered off lights will be turned on before starting the effect. default: true selector: boolean: effect_stop: - name: Stop effect - description: Stop a running effect. target: entity: integration: lifx diff --git a/homeassistant/components/lifx/strings.json b/homeassistant/components/lifx/strings.json index 69055d6bbc67cb..cff9b572cc6285 100644 --- a/homeassistant/components/lifx/strings.json +++ b/homeassistant/components/lifx/strings.json @@ -45,5 +45,181 @@ "name": "RSSI" } } + }, + "services": { + "set_hev_cycle_state": { + "name": "Set HEV cycle state", + "description": "Controls the HEV LEDs on a LIFX Clean bulb.", + "fields": { + "power": { + "name": "Enable", + "description": "Start or stop a Clean cycle." + }, + "duration": { + "name": "Duration", + "description": "How long the HEV LEDs will remain on. Uses the configured default duration if not specified." + } + } + }, + "set_state": { + "name": "Set State", + "description": "Sets a color/brightness and possibly turn the light on/off.", + "fields": { + "infrared": { + "name": "Infrared", + "description": "Automatic infrared level when light brightness is low." + }, + "zones": { + "name": "Zones", + "description": "List of zone numbers to affect (8 per LIFX Z, starts at 0)." + }, + "transition": { + "name": "Transition", + "description": "Duration it takes to get to the final state." + }, + "power": { + "name": "Power", + "description": "Turn the light on or off. Leave out to keep the power as it is." + } + } + }, + "effect_pulse": { + "name": "Pulse effect", + "description": "Runs a flash effect by changing to a color and back.", + "fields": { + "mode": { + "name": "Mode", + "description": "Decides how colors are changed." + }, + "brightness": { + "name": "Brightness value", + "description": "Number indicating brightness of the temporary color, where 1 is the minimum brightness and 255 is the maximum brightness supported by the light." + }, + "brightness_pct": { + "name": "Brightness", + "description": "Percentage indicating the brightness of the temporary color, where 1 is the minimum brightness and 100 is the maximum brightness supported by the light." + }, + "color_name": { + "name": "Color name", + "description": "A human readable color name." + }, + "rgb_color": { + "name": "RGB color", + "description": "The temporary color in RGB-format." + }, + "period": { + "name": "Period", + "description": "Duration of the effect." + }, + "cycles": { + "name": "Cycles", + "description": "Number of times the effect should run." + }, + "power_on": { + "name": "Power on", + "description": "Powered off lights are temporarily turned on during the effect." + } + } + }, + "effect_colorloop": { + "name": "Color loop effect", + "description": "Runs an effect with looping colors.", + "fields": { + "brightness": { + "name": "Brightness value", + "description": "Number indicating brightness of the color loop, where 1 is the minimum brightness and 255 is the maximum brightness supported by the light." + }, + "brightness_pct": { + "name": "Brightness", + "description": "Percentage indicating the brightness of the color loop, where 1 is the minimum brightness and 100 is the maximum brightness supported by the light." + }, + "saturation_min": { + "name": "Minimum saturation", + "description": "Percentage indicating the minimum saturation of the colors in the loop." + }, + "saturation_max": { + "name": "Maximum saturation", + "description": "Percentage indicating the maximum saturation of the colors in the loop." + }, + "period": { + "name": "Period", + "description": "Duration between color changes." + }, + "change": { + "name": "Change", + "description": "Hue movement per period, in degrees on a color wheel." + }, + "spread": { + "name": "Spread", + "description": "Maximum hue difference between participating lights, in degrees on a color wheel." + }, + "power_on": { + "name": "Power on", + "description": "Powered off lights are temporarily turned on during the effect." + } + } + }, + "effect_move": { + "name": "Move effect", + "description": "Starts the firmware-based Move effect on a LIFX Z, Lightstrip or Beam.", + "fields": { + "speed": { + "name": "Speed", + "description": "How long in seconds for the effect to move across the length of the light." + }, + "direction": { + "name": "Direction", + "description": "Direction the effect will move across the device." + }, + "theme": { + "name": "Theme", + "description": "(Optional) set one of the predefined themes onto the device before starting the effect." + }, + "power_on": { + "name": "Power on", + "description": "Powered off lights will be turned on before starting the effect." + } + } + }, + "effect_flame": { + "name": "Flame effect", + "description": "Starts the firmware-based Flame effect on LIFX Tiles or Candle.", + "fields": { + "speed": { + "name": "Speed", + "description": "How fast the flames will move." + }, + "power_on": { + "name": "Power on", + "description": "Powered off lights will be turned on before starting the effect." + } + } + }, + "effect_morph": { + "name": "Morph effect", + "description": "Starts the firmware-based Morph effect on LIFX Tiles on Candle.", + "fields": { + "speed": { + "name": "Speed", + "description": "How fast the colors will move." + }, + "palette": { + "name": "Palette", + "description": "List of at least 2 and at most 16 colors as hue (0-360), saturation (0-100), brightness (0-100) and kelvin (1500-900) values to use for this effect. Overrides the theme attribute." + }, + "theme": { + "name": "Theme", + "description": "Predefined color theme to use for the effect. Overridden by the palette attribute." + }, + "power_on": { + "name": "Power on", + "description": "Powered off lights will be turned on before starting the effect." + } + } + }, + "effect_stop": { + "name": "Stop effect", + "description": "Stops a running effect." + } } } diff --git a/homeassistant/components/litterrobot/services.yaml b/homeassistant/components/litterrobot/services.yaml index 164445e375f375..48d17dfdcf72c5 100644 --- a/homeassistant/components/litterrobot/services.yaml +++ b/homeassistant/components/litterrobot/services.yaml @@ -1,21 +1,15 @@ # Describes the format for available Litter-Robot services set_sleep_mode: - name: Set sleep mode - description: Set the sleep mode and start time. target: entity: integration: litterrobot fields: enabled: - name: Enabled - description: Whether sleep mode should be enabled. required: true selector: boolean: start_time: - name: Start time - description: The start time at which the Litter-Robot will enter sleep mode and prevent an automatic clean cycle for 8 hours. required: false example: '"22:30:00"' selector: diff --git a/homeassistant/components/litterrobot/strings.json b/homeassistant/components/litterrobot/strings.json index 5a6a0bf6998f38..e5cd35703f3edb 100644 --- a/homeassistant/components/litterrobot/strings.json +++ b/homeassistant/components/litterrobot/strings.json @@ -137,5 +137,21 @@ "name": "Firmware" } } + }, + "services": { + "set_sleep_mode": { + "name": "Set sleep mode", + "description": "Sets the sleep mode and start time.", + "fields": { + "enabled": { + "name": "Enabled", + "description": "Whether sleep mode should be enabled." + }, + "start_time": { + "name": "Start time", + "description": "The start time at which the Litter-Robot will enter sleep mode and prevent an automatic clean cycle for 8 hours." + } + } + } } } diff --git a/homeassistant/components/local_file/services.yaml b/homeassistant/components/local_file/services.yaml index f4382decb0ff4f..5fc0b11f4c2d0d 100644 --- a/homeassistant/components/local_file/services.yaml +++ b/homeassistant/components/local_file/services.yaml @@ -1,17 +1,11 @@ update_file_path: - name: Update file path - description: Use this service to change the file displayed by the camera. fields: entity_id: - name: Entity - description: Name of the entity_id of the camera to update. required: true selector: entity: domain: camera file_path: - name: file path - description: The full path to the new image file to be displayed. required: true example: "/config/www/images/image.jpg" selector: diff --git a/homeassistant/components/local_file/strings.json b/homeassistant/components/local_file/strings.json new file mode 100644 index 00000000000000..3f977fc941ea52 --- /dev/null +++ b/homeassistant/components/local_file/strings.json @@ -0,0 +1,18 @@ +{ + "services": { + "update_file_path": { + "name": "Updates file path", + "description": "Use this service to change the file displayed by the camera.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name of the entity_id of the camera to update." + }, + "file_path": { + "name": "File path", + "description": "The full path to the new image file to be displayed." + } + } + } + } +} diff --git a/homeassistant/components/logi_circle/services.yaml b/homeassistant/components/logi_circle/services.yaml index 10df6c564b481d..cb855a953a6901 100644 --- a/homeassistant/components/logi_circle/services.yaml +++ b/homeassistant/components/logi_circle/services.yaml @@ -1,19 +1,13 @@ # Describes the format for available Logi Circle services set_config: - name: Set config - description: Set a configuration property. fields: entity_id: - name: Entity - description: Name(s) of entities to apply the operation mode to. selector: entity: integration: logi_circle domain: camera mode: - name: Mode - description: "Operation mode. Allowed values: LED, RECORDING_MODE." required: true selector: select: @@ -21,52 +15,36 @@ set_config: - "LED" - "RECORDING_MODE" value: - name: Value - description: "Operation value." required: true selector: boolean: livestream_snapshot: - name: Livestream snapshot - description: Take a snapshot from the camera's livestream. Will wake the camera from sleep if required. fields: entity_id: - name: Entity - description: Name(s) of entities to create snapshots from. selector: entity: integration: logi_circle domain: camera filename: - name: File name - description: Template of a Filename. Variable is entity_id. required: true example: "/tmp/snapshot_{{ entity_id }}.jpg" selector: text: livestream_record: - name: Livestream record - description: Take a video recording from the camera's livestream. fields: entity_id: - name: Entity - description: Name(s) of entities to create recordings from. selector: entity: integration: logi_circle domain: camera filename: - name: File name - description: Template of a Filename. Variable is entity_id. required: true example: "/tmp/snapshot_{{ entity_id }}.mp4" selector: text: duration: - name: Duration - description: Recording duration. required: true selector: number: diff --git a/homeassistant/components/logi_circle/strings.json b/homeassistant/components/logi_circle/strings.json index a73ade9311ce1c..9a06fb45ad24ad 100644 --- a/homeassistant/components/logi_circle/strings.json +++ b/homeassistant/components/logi_circle/strings.json @@ -4,7 +4,9 @@ "user": { "title": "Authentication Provider", "description": "Pick via which authentication provider you want to authenticate with Logi Circle.", - "data": { "flow_impl": "Provider" } + "data": { + "flow_impl": "Provider" + } }, "auth": { "title": "Authenticate with Logi Circle", @@ -22,5 +24,57 @@ "external_setup": "Logi Circle successfully configured from another flow.", "missing_configuration": "[%key:common::config_flow::abort::oauth2_missing_configuration%]" } + }, + "services": { + "set_config": { + "name": "Set config", + "description": "Sets a configuration property.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name(s) of entities to apply the operation mode to." + }, + "mode": { + "name": "Mode", + "description": "Operation mode. Allowed values: LED, RECORDING_MODE." + }, + "value": { + "name": "Value", + "description": "Operation value." + } + } + }, + "livestream_snapshot": { + "name": "Livestream snapshot", + "description": "Takes a snapshot from the camera's livestream. Will wake the camera from sleep if required.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name(s) of entities to create snapshots from." + }, + "filename": { + "name": "File name", + "description": "Template of a Filename. Variable is entity_id." + } + } + }, + "livestream_record": { + "name": "Livestream record", + "description": "Takes a video recording from the camera's livestream.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name(s) of entities to create recordings from." + }, + "filename": { + "name": "File name", + "description": "Template of a Filename. Variable is entity_id." + }, + "duration": { + "name": "Duration", + "description": "Recording duration." + } + } + } } } diff --git a/homeassistant/components/lyric/services.yaml b/homeassistant/components/lyric/services.yaml index 69c802d90aaa2c..c3c4bc640bf583 100644 --- a/homeassistant/components/lyric/services.yaml +++ b/homeassistant/components/lyric/services.yaml @@ -1,6 +1,4 @@ set_hold_time: - name: Set Hold Time - description: "Sets the time to hold until" target: device: integration: lyric @@ -9,8 +7,6 @@ set_hold_time: domain: climate fields: time_period: - name: Time Period - description: Time to hold until default: "01:00:00" example: "01:00:00" required: true diff --git a/homeassistant/components/lyric/strings.json b/homeassistant/components/lyric/strings.json index 3c9cd6043dfa25..2271d4201f65dc 100644 --- a/homeassistant/components/lyric/strings.json +++ b/homeassistant/components/lyric/strings.json @@ -17,5 +17,17 @@ "create_entry": { "default": "[%key:common::config_flow::create_entry::authenticated%]" } + }, + "services": { + "set_hold_time": { + "name": "Set Hold Time", + "description": "Sets the time to hold until.", + "fields": { + "time_period": { + "name": "Time Period", + "description": "Time to hold until." + } + } + } } } diff --git a/homeassistant/components/matrix/services.yaml b/homeassistant/components/matrix/services.yaml index 9b5171d1483e5d..f2ce72397d4f83 100644 --- a/homeassistant/components/matrix/services.yaml +++ b/homeassistant/components/matrix/services.yaml @@ -1,24 +1,16 @@ send_message: - name: Send message - description: Send message to target room(s) fields: message: - name: Message - description: The message to be sent. required: true example: This is a message I am sending to matrix selector: text: target: - name: Target - description: A list of room(s) to send the message to. required: true example: "#hasstest:matrix.org" selector: text: data: - name: Data - description: Extended information of notification. Supports list of images. Supports message format. Optional. example: "{'images': ['/tmp/test.jpg'], 'format': 'text'}" selector: object: diff --git a/homeassistant/components/matrix/strings.json b/homeassistant/components/matrix/strings.json new file mode 100644 index 00000000000000..03d4c5728a5397 --- /dev/null +++ b/homeassistant/components/matrix/strings.json @@ -0,0 +1,22 @@ +{ + "services": { + "send_message": { + "name": "Send message", + "description": "Sends message to target room(s).", + "fields": { + "message": { + "name": "Message", + "description": "The message to be sent." + }, + "target": { + "name": "Target", + "description": "A list of room(s) to send the message to." + }, + "data": { + "name": "Data", + "description": "Extended information of notification. Supports list of images. Supports message format. Optional." + } + } + } + } +} diff --git a/homeassistant/components/mazda/services.yaml b/homeassistant/components/mazda/services.yaml index 1abf8bd5dea2e6..b401c01f3a3465 100644 --- a/homeassistant/components/mazda/services.yaml +++ b/homeassistant/components/mazda/services.yaml @@ -1,17 +1,11 @@ send_poi: - name: Send POI - description: Send a GPS location to the vehicle's navigation system as a POI (Point of Interest). Requires a navigation SD card installed in the vehicle. fields: device_id: - name: Vehicle - description: The vehicle to send the GPS location to required: true selector: device: integration: mazda latitude: - name: Latitude - description: The latitude of the location to send example: 12.34567 required: true selector: @@ -21,8 +15,6 @@ send_poi: unit_of_measurement: ° mode: box longitude: - name: Longitude - description: The longitude of the location to send example: -34.56789 required: true selector: @@ -32,8 +24,6 @@ send_poi: unit_of_measurement: ° mode: box poi_name: - name: POI name - description: A friendly name for the location example: Work required: true selector: diff --git a/homeassistant/components/mazda/strings.json b/homeassistant/components/mazda/strings.json index d2cc1bcfec97d9..9c881e6324fc4c 100644 --- a/homeassistant/components/mazda/strings.json +++ b/homeassistant/components/mazda/strings.json @@ -20,5 +20,29 @@ "description": "Please enter the email address and password you use to log into the MyMazda mobile app." } } + }, + "services": { + "send_poi": { + "name": "Send POI", + "description": "Sends a GPS location to the vehicle's navigation system as a POI (Point of Interest). Requires a navigation SD card installed in the vehicle.", + "fields": { + "device_id": { + "name": "Vehicle", + "description": "The vehicle to send the GPS location to." + }, + "latitude": { + "name": "Latitude", + "description": "The latitude of the location to send." + }, + "longitude": { + "name": "Longitude", + "description": "The longitude of the location to send." + }, + "poi_name": { + "name": "POI name", + "description": "A friendly name for the location." + } + } + } } } diff --git a/homeassistant/components/media_extractor/services.yaml b/homeassistant/components/media_extractor/services.yaml index 0b7295bd7bfcf9..8af2d12d0e9015 100644 --- a/homeassistant/components/media_extractor/services.yaml +++ b/homeassistant/components/media_extractor/services.yaml @@ -1,20 +1,14 @@ play_media: - name: Play media - description: Downloads file from given URL. target: entity: domain: media_player fields: media_content_id: - name: Media content ID - description: The ID of the content to play. Platform dependent. required: true example: "https://soundcloud.com/bruttoband/brutto-11" selector: text: media_content_type: - name: Media content type - description: The type of the content to play. Must be one of MUSIC, TVSHOW, VIDEO, EPISODE, CHANNEL or PLAYLIST MUSIC. required: true selector: select: diff --git a/homeassistant/components/media_extractor/strings.json b/homeassistant/components/media_extractor/strings.json new file mode 100644 index 00000000000000..0cdffd5d508f74 --- /dev/null +++ b/homeassistant/components/media_extractor/strings.json @@ -0,0 +1,18 @@ +{ + "services": { + "play_media": { + "name": "Play media", + "description": "Downloads file from given URL.", + "fields": { + "media_content_id": { + "name": "Media content ID", + "description": "The ID of the content to play. Platform dependent." + }, + "media_content_type": { + "name": "Media content type", + "description": "The type of the content to play. Must be one of MUSIC, TVSHOW, VIDEO, EPISODE, CHANNEL or PLAYLIST MUSIC." + } + } + } + } +} diff --git a/homeassistant/components/melcloud/services.yaml b/homeassistant/components/melcloud/services.yaml index f470076ee7fd65..f13cd646388a15 100644 --- a/homeassistant/components/melcloud/services.yaml +++ b/homeassistant/components/melcloud/services.yaml @@ -1,34 +1,22 @@ set_vane_horizontal: - name: Set vane horizontal - description: Sets horizontal vane position. target: entity: integration: melcloud domain: climate fields: position: - name: Position - description: > - Horizontal vane position. Possible options can be found in the - vane_horizontal_positions state attribute. required: true example: "auto" selector: text: set_vane_vertical: - name: Set vane vertical - description: Sets vertical vane position. target: entity: integration: melcloud domain: climate fields: position: - name: Position - description: > - Vertical vane position. Possible options can be found in the - vane_vertical_positions state attribute. required: true example: "auto" selector: diff --git a/homeassistant/components/melcloud/strings.json b/homeassistant/components/melcloud/strings.json index a1bce80d7ad425..bef65e288805b3 100644 --- a/homeassistant/components/melcloud/strings.json +++ b/homeassistant/components/melcloud/strings.json @@ -18,5 +18,27 @@ "abort": { "already_configured": "MELCloud integration already configured for this email. Access token has been refreshed." } + }, + "services": { + "set_vane_horizontal": { + "name": "Set vane horizontal", + "description": "Sets horizontal vane position.", + "fields": { + "position": { + "name": "Position", + "description": "Horizontal vane position. Possible options can be found in the vane_horizontal_positions state attribute.\n." + } + } + }, + "set_vane_vertical": { + "name": "Set vane vertical", + "description": "Sets vertical vane position.", + "fields": { + "position": { + "name": "Position", + "description": "Vertical vane position. Possible options can be found in the vane_vertical_positions state attribute.\n." + } + } + } } } diff --git a/homeassistant/components/microsoft_face/services.yaml b/homeassistant/components/microsoft_face/services.yaml index e27e29dfc6fad3..13078495b43bd6 100644 --- a/homeassistant/components/microsoft_face/services.yaml +++ b/homeassistant/components/microsoft_face/services.yaml @@ -1,93 +1,61 @@ create_group: - name: Create group - description: Create a new person group. fields: name: - name: Name - description: Name of the group. required: true example: family selector: text: create_person: - name: Create person - description: Create a new person in the group. fields: group: - name: Group - description: Name of the group required: true example: family selector: text: name: - name: Name - description: Name of the person required: true example: Hans selector: text: delete_group: - name: Delete group - description: Delete a new person group. fields: name: - name: Name - description: Name of the group. required: true example: family selector: text: delete_person: - name: Delete person - description: Delete a person in the group. fields: group: - name: Group - description: Name of the group. required: true example: family selector: text: name: - name: Name - description: Name of the person. required: true example: Hans selector: text: face_person: - name: Face person - description: Add a new picture to a person. fields: camera_entity: - name: Camera entity - description: Camera to take a picture. required: true example: camera.door selector: text: group: - name: Group - description: Name of the group. required: true example: family selector: text: person: - name: Person - description: Name of the person. required: true example: Hans selector: text: train_group: - name: Train group - description: Train a person group. fields: group: - name: Group - description: Name of the group required: true example: family selector: diff --git a/homeassistant/components/microsoft_face/strings.json b/homeassistant/components/microsoft_face/strings.json new file mode 100644 index 00000000000000..b1008336992f05 --- /dev/null +++ b/homeassistant/components/microsoft_face/strings.json @@ -0,0 +1,80 @@ +{ + "services": { + "create_group": { + "name": "Create group", + "description": "Creates a new person group.", + "fields": { + "name": { + "name": "Name", + "description": "Name of the group." + } + } + }, + "create_person": { + "name": "Create person", + "description": "Creates a new person in the group.", + "fields": { + "group": { + "name": "Group", + "description": "Name of the group." + }, + "name": { + "name": "Name", + "description": "Name of the person." + } + } + }, + "delete_group": { + "name": "Delete group", + "description": "Deletes a new person group.", + "fields": { + "name": { + "name": "Name", + "description": "Name of the group." + } + } + }, + "delete_person": { + "name": "Delete person", + "description": "Deletes a person in the group.", + "fields": { + "group": { + "name": "Group", + "description": "Name of the group." + }, + "name": { + "name": "Name", + "description": "Name of the person." + } + } + }, + "face_person": { + "name": "Face person", + "description": "Adds a new picture to a person.", + "fields": { + "camera_entity": { + "name": "Camera entity", + "description": "Camera to take a picture." + }, + "group": { + "name": "Group", + "description": "Name of the group." + }, + "person": { + "name": "Person", + "description": "Name of the person." + } + } + }, + "train_group": { + "name": "Train group", + "description": "Trains a person group.", + "fields": { + "group": { + "name": "Group", + "description": "Name of the group." + } + } + } + } +} diff --git a/homeassistant/components/mill/services.yaml b/homeassistant/components/mill/services.yaml index ad5cff4a5ff1b0..14e2196eb8350b 100644 --- a/homeassistant/components/mill/services.yaml +++ b/homeassistant/components/mill/services.yaml @@ -1,33 +1,23 @@ set_room_temperature: - name: Set room temperature - description: Set Mill room temperatures. fields: room_name: - name: Room name - description: Name of room to change. required: true example: "kitchen" selector: text: away_temp: - name: Away temperature - description: Away temp. selector: number: min: 0 max: 100 unit_of_measurement: "°" comfort_temp: - name: Comfort temperature - description: Comfort temp. selector: number: min: 0 max: 100 unit_of_measurement: "°" sleep_temp: - name: Sleep temperature - description: Sleep temp. selector: number: min: 0 diff --git a/homeassistant/components/mill/strings.json b/homeassistant/components/mill/strings.json index 5f4cec1336ec64..caeea189c0e13a 100644 --- a/homeassistant/components/mill/strings.json +++ b/homeassistant/components/mill/strings.json @@ -26,5 +26,29 @@ "description": "Local IP address of the device." } } + }, + "services": { + "set_room_temperature": { + "name": "Set room temperature", + "description": "Sets Mill room temperatures.", + "fields": { + "room_name": { + "name": "Room name", + "description": "Name of room to change." + }, + "away_temp": { + "name": "Away temperature", + "description": "Away temp." + }, + "comfort_temp": { + "name": "Comfort temperature", + "description": "Comfort temp." + }, + "sleep_temp": { + "name": "Sleep temperature", + "description": "Sleep temp." + } + } + } } } diff --git a/homeassistant/components/minio/services.yaml b/homeassistant/components/minio/services.yaml index 39e430ab165ba1..b40797bc1651c4 100644 --- a/homeassistant/components/minio/services.yaml +++ b/homeassistant/components/minio/services.yaml @@ -1,69 +1,47 @@ get: - name: Get - description: Download file from Minio. fields: bucket: - name: Bucket - description: Bucket to use. required: true example: camera-files selector: text: key: - name: Kay - description: Object key of the file. required: true example: front_camera/2018/01/02/snapshot_12512514.jpg selector: text: file_path: - name: File path - description: File path on local filesystem. required: true example: /data/camera_files/snapshot.jpg selector: text: put: - name: Put - description: Upload file to Minio. fields: bucket: - name: Bucket - description: Bucket to use. required: true example: camera-files selector: text: key: - name: Key - description: Object key of the file. required: true example: front_camera/2018/01/02/snapshot_12512514.jpg selector: text: file_path: - name: File path - description: File path on local filesystem. required: true example: /data/camera_files/snapshot.jpg selector: text: remove: - name: Remove - description: Delete file from Minio. fields: bucket: - name: Bucket - description: Bucket to use. required: true example: camera-files selector: text: key: - name: Key - description: Object key of the file. required: true example: front_camera/2018/01/02/snapshot_12512514.jpg selector: diff --git a/homeassistant/components/minio/strings.json b/homeassistant/components/minio/strings.json new file mode 100644 index 00000000000000..21902ad1825b8a --- /dev/null +++ b/homeassistant/components/minio/strings.json @@ -0,0 +1,54 @@ +{ + "services": { + "get": { + "name": "Get", + "description": "Downloads file from Minio.", + "fields": { + "bucket": { + "name": "Bucket", + "description": "Bucket to use." + }, + "key": { + "name": "Kay", + "description": "Object key of the file." + }, + "file_path": { + "name": "File path", + "description": "File path on local filesystem." + } + } + }, + "put": { + "name": "Put", + "description": "Uploads file to Minio.", + "fields": { + "bucket": { + "name": "Bucket", + "description": "Bucket to use." + }, + "key": { + "name": "Key", + "description": "Object key of the file." + }, + "file_path": { + "name": "File path", + "description": "File path on local filesystem." + } + } + }, + "remove": { + "name": "Remove", + "description": "Deletes file from Minio.", + "fields": { + "bucket": { + "name": "Bucket", + "description": "Bucket to use." + }, + "key": { + "name": "Key", + "description": "Object key of the file." + } + } + } + } +} diff --git a/homeassistant/components/modbus/services.yaml b/homeassistant/components/modbus/services.yaml index 07acf0a72df54e..8dafa911ada1d1 100644 --- a/homeassistant/components/modbus/services.yaml +++ b/homeassistant/components/modbus/services.yaml @@ -1,92 +1,62 @@ reload: - name: Reload - description: Reload all modbus entities. write_coil: - name: Write coil - description: Write to a modbus coil. fields: address: - name: Address - description: Address of the register to write to. required: true selector: number: min: 0 max: 65535 state: - name: State - description: State to write. required: true example: "0 or [1,0]" selector: object: slave: - name: Slave - description: Address of the modbus unit/slave. required: false selector: number: min: 1 max: 255 hub: - name: Hub - description: Modbus hub name. example: "hub1" default: "modbus_hub" selector: text: write_register: - name: Write register - description: Write to a modbus holding register. fields: address: - name: Address - description: Address of the holding register to write to. required: true selector: number: min: 0 max: 65535 slave: - name: Slave - description: Address of the modbus unit/slave. required: false selector: number: min: 1 max: 255 value: - name: Value - description: Value (single value or array) to write. required: true example: "0 or [4,0]" selector: object: hub: - name: Hub - description: Modbus hub name. example: "hub1" default: "modbus_hub" selector: text: stop: - name: Stop - description: Stop modbus hub. fields: hub: - name: Hub - description: Modbus hub name. example: "hub1" default: "modbus_hub" selector: text: restart: - name: Restart - description: Restart modbus hub (if running stop then start). fields: hub: - name: Hub - description: Modbus hub name. example: "hub1" default: "modbus_hub" selector: diff --git a/homeassistant/components/modbus/strings.json b/homeassistant/components/modbus/strings.json new file mode 100644 index 00000000000000..ad07a4d7565966 --- /dev/null +++ b/homeassistant/components/modbus/strings.json @@ -0,0 +1,72 @@ +{ + "services": { + "reload": { + "name": "Reload", + "description": "Reloads all modbus entities." + }, + "write_coil": { + "name": "Write coil", + "description": "Writes to a modbus coil.", + "fields": { + "address": { + "name": "Address", + "description": "Address of the register to write to." + }, + "state": { + "name": "State", + "description": "State to write." + }, + "slave": { + "name": "Slave", + "description": "Address of the modbus unit/slave." + }, + "hub": { + "name": "Hub", + "description": "Modbus hub name." + } + } + }, + "write_register": { + "name": "Write register", + "description": "Writes to a modbus holding register.", + "fields": { + "address": { + "name": "Address", + "description": "Address of the holding register to write to." + }, + "slave": { + "name": "Slave", + "description": "Address of the modbus unit/slave." + }, + "value": { + "name": "Value", + "description": "Value (single value or array) to write." + }, + "hub": { + "name": "Hub", + "description": "Modbus hub name." + } + } + }, + "stop": { + "name": "Stop", + "description": "Stops modbus hub.", + "fields": { + "hub": { + "name": "Hub", + "description": "Modbus hub name." + } + } + }, + "restart": { + "name": "Restart", + "description": "Restarts modbus hub (if running stop then start).", + "fields": { + "hub": { + "name": "Hub", + "description": "Modbus hub name." + } + } + } + } +} diff --git a/homeassistant/components/modern_forms/services.yaml b/homeassistant/components/modern_forms/services.yaml index ce3c29f39b527b..07150f530be477 100644 --- a/homeassistant/components/modern_forms/services.yaml +++ b/homeassistant/components/modern_forms/services.yaml @@ -1,14 +1,10 @@ set_light_sleep_timer: - name: Set light sleep timer - description: Set a sleep timer on a Modern Forms light. target: entity: integration: modern_forms domain: light fields: sleep_time: - name: Sleep Time - description: Number of minutes to set the timer. required: true example: "900" selector: @@ -17,23 +13,17 @@ set_light_sleep_timer: max: 1440 unit_of_measurement: minutes clear_light_sleep_timer: - name: Clear light sleep timer - description: Clear the sleep timer on a Modern Forms light. target: entity: integration: modern_forms domain: light set_fan_sleep_timer: - name: Set fan sleep timer - description: Set a sleep timer on a Modern Forms fan. target: entity: integration: modern_forms domain: fan fields: sleep_time: - name: Sleep Time - description: Number of minutes to set the timer. required: true example: "900" selector: @@ -42,8 +32,6 @@ set_fan_sleep_timer: max: 1440 unit_of_measurement: minutes clear_fan_sleep_timer: - name: Clear fan sleep timer - description: Clear the sleep timer on a Modern Forms fan. target: entity: integration: modern_forms diff --git a/homeassistant/components/modern_forms/strings.json b/homeassistant/components/modern_forms/strings.json index fc30709960b80d..397d7267bc092e 100644 --- a/homeassistant/components/modern_forms/strings.json +++ b/homeassistant/components/modern_forms/strings.json @@ -20,5 +20,35 @@ "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]" } + }, + "services": { + "set_light_sleep_timer": { + "name": "Set light sleep timer", + "description": "Sets a sleep timer on a Modern Forms light.", + "fields": { + "sleep_time": { + "name": "Sleep time", + "description": "Number of minutes to set the timer." + } + } + }, + "clear_light_sleep_timer": { + "name": "Clear light sleep timer", + "description": "Clears the sleep timer on a Modern Forms light." + }, + "set_fan_sleep_timer": { + "name": "Set fan sleep timer", + "description": "Sets a sleep timer on a Modern Forms fan.", + "fields": { + "sleep_time": { + "name": "Sleep time", + "description": "Number of minutes to set the timer." + } + } + }, + "clear_fan_sleep_timer": { + "name": "Clear fan sleep timer", + "description": "Clears the sleep timer on a Modern Forms fan." + } } } diff --git a/homeassistant/components/monoprice/services.yaml b/homeassistant/components/monoprice/services.yaml index 93275fd2a1dc5d..7f3039509ba496 100644 --- a/homeassistant/components/monoprice/services.yaml +++ b/homeassistant/components/monoprice/services.yaml @@ -1,14 +1,10 @@ snapshot: - name: Snapshot - description: Take a snapshot of the media player zone. target: entity: integration: monoprice domain: media_player restore: - name: Restore - description: Restore a snapshot of the media player zone. target: entity: integration: monoprice diff --git a/homeassistant/components/monoprice/strings.json b/homeassistant/components/monoprice/strings.json index 008c182f41b063..4ecf4cfee45caa 100644 --- a/homeassistant/components/monoprice/strings.json +++ b/homeassistant/components/monoprice/strings.json @@ -36,5 +36,15 @@ } } } + }, + "services": { + "snapshot": { + "name": "Snapshot", + "description": "Takes a snapshot of the media player zone." + }, + "restore": { + "name": "Restore", + "description": "Restores a snapshot of the media player zone." + } } } diff --git a/homeassistant/components/motion_blinds/services.yaml b/homeassistant/components/motion_blinds/services.yaml index d37d6bb5be83c4..7b18979ed0ed8a 100644 --- a/homeassistant/components/motion_blinds/services.yaml +++ b/homeassistant/components/motion_blinds/services.yaml @@ -1,16 +1,12 @@ # Describes the format for available motion blinds services set_absolute_position: - name: Set absolute position - description: "Set the absolute position of the cover." target: entity: integration: motion_blinds domain: cover fields: absolute_position: - name: Absolute position - description: Absolute position to move to. required: true selector: number: @@ -18,16 +14,12 @@ set_absolute_position: max: 100 unit_of_measurement: "%" tilt_position: - name: Tilt position - description: Tilt position to move to. selector: number: min: 0 max: 100 unit_of_measurement: "%" width: - name: Width - description: Specify the width that is covered, only for TDBU Combined entities. selector: number: min: 1 diff --git a/homeassistant/components/motion_blinds/strings.json b/homeassistant/components/motion_blinds/strings.json index 47c0867187e894..0e0a32bfb2420e 100644 --- a/homeassistant/components/motion_blinds/strings.json +++ b/homeassistant/components/motion_blinds/strings.json @@ -40,5 +40,25 @@ } } } + }, + "services": { + "set_absolute_position": { + "name": "Set absolute position", + "description": "Sets the absolute position of the cover.", + "fields": { + "absolute_position": { + "name": "Absolute position", + "description": "Absolute position to move to." + }, + "tilt_position": { + "name": "Tilt position", + "description": "Tilt position to move to." + }, + "width": { + "name": "Width", + "description": "Specify the width that is covered, only for TDBU Combined entities." + } + } + } } } diff --git a/homeassistant/components/motioneye/services.yaml b/homeassistant/components/motioneye/services.yaml index 2970124c000652..c5a11db8a6f782 100644 --- a/homeassistant/components/motioneye/services.yaml +++ b/homeassistant/components/motioneye/services.yaml @@ -1,6 +1,4 @@ set_text_overlay: - name: Set Text Overlay - description: Sets the text overlay for a camera. target: device: integration: motioneye @@ -8,8 +6,6 @@ set_text_overlay: integration: motioneye fields: left_text: - name: Left Text Overlay - description: Text to display on the left required: false advanced: false example: "timestamp" @@ -22,8 +18,6 @@ set_text_overlay: - "timestamp" - "custom-text" custom_left_text: - name: Left Custom Text - description: Custom text to display on the left required: false advanced: false example: "Hello on the left!" @@ -32,8 +26,6 @@ set_text_overlay: text: multiline: true right_text: - name: Right Text Overlay - description: Text to display on the right required: false advanced: false example: "timestamp" @@ -46,8 +38,6 @@ set_text_overlay: - "timestamp" - "custom-text" custom_right_text: - name: Right Custom Text - description: Custom text to display on the right required: false advanced: false example: "Hello on the right!" @@ -57,8 +47,6 @@ set_text_overlay: multiline: true action: - name: Action - description: Trigger a motionEye action target: device: integration: motioneye @@ -66,8 +54,6 @@ action: integration: motioneye fields: action: - name: Action - description: Action to trigger required: true advanced: false example: "snapshot" @@ -101,8 +87,6 @@ action: - "preset9" snapshot: - name: Snapshot - description: Trigger a motionEye still snapshot target: device: integration: motioneye diff --git a/homeassistant/components/motioneye/strings.json b/homeassistant/components/motioneye/strings.json index f92fa11cd77170..fdf73cd8cf8ee7 100644 --- a/homeassistant/components/motioneye/strings.json +++ b/homeassistant/components/motioneye/strings.json @@ -36,5 +36,43 @@ } } } + }, + "services": { + "set_text_overlay": { + "name": "Set text overlay", + "description": "Sets the text overlay for a camera.", + "fields": { + "left_text": { + "name": "Left text overlay", + "description": "Text to display on the left." + }, + "custom_left_text": { + "name": "Left custom text", + "description": "Custom text to display on the left." + }, + "right_text": { + "name": "Right text overlay", + "description": "Text to display on the right." + }, + "custom_right_text": { + "name": "Right custom text", + "description": "Custom text to display on the right." + } + } + }, + "action": { + "name": "Action", + "description": "Triggers a motionEye action.", + "fields": { + "action": { + "name": "Action", + "description": "Action to trigger." + } + } + }, + "snapshot": { + "name": "Snapshot", + "description": "Triggers a motionEye still snapshot." + } } } From 90d839724c5fd27855215ffdb2fac502370a9f1c Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 00:33:37 +0200 Subject: [PATCH 064/154] Migrate integration services (N-P) to support translations (#96376) --- homeassistant/components/neato/services.yaml | 10 -- homeassistant/components/neato/strings.json | 24 +++ .../components/ness_alarm/services.yaml | 10 -- .../components/ness_alarm/strings.json | 28 +++ homeassistant/components/nest/services.yaml | 22 --- homeassistant/components/nest/strings.json | 52 ++++++ .../components/netatmo/services.yaml | 25 --- homeassistant/components/netatmo/strings.json | 50 ++++++ .../components/netgear_lte/services.yaml | 21 --- .../components/netgear_lte/strings.json | 57 ++++++ homeassistant/components/nexia/services.yaml | 14 -- homeassistant/components/nexia/strings.json | 36 ++++ .../components/nissan_leaf/services.yaml | 13 -- .../components/nissan_leaf/strings.json | 24 +++ homeassistant/components/nuki/services.yaml | 8 - homeassistant/components/nuki/strings.json | 22 +++ homeassistant/components/nx584/services.yaml | 8 - homeassistant/components/nx584/strings.json | 24 +++ homeassistant/components/nzbget/services.yaml | 10 -- homeassistant/components/nzbget/strings.json | 20 +++ homeassistant/components/ombi/services.yaml | 14 -- homeassistant/components/ombi/strings.json | 38 ++++ .../components/omnilogic/services.yaml | 4 - .../components/omnilogic/strings.json | 12 ++ homeassistant/components/onvif/services.yaml | 18 -- homeassistant/components/onvif/strings.json | 40 +++++ .../components/openhome/services.yaml | 4 - .../components/openhome/strings.json | 14 ++ .../components/opentherm_gw/services.yaml | 105 ----------- .../components/opentherm_gw/strings.json | 164 ++++++++++++++++++ .../components/pi_hole/services.yaml | 4 - homeassistant/components/pi_hole/strings.json | 64 +++++-- homeassistant/components/picnic/services.yaml | 13 -- homeassistant/components/picnic/strings.json | 24 +++ .../components/pilight/services.yaml | 4 - homeassistant/components/pilight/strings.json | 14 ++ homeassistant/components/ping/services.yaml | 2 - homeassistant/components/ping/strings.json | 8 + homeassistant/components/plex/services.yaml | 8 - homeassistant/components/plex/strings.json | 20 +++ .../components/profiler/services.yaml | 32 ---- .../components/profiler/strings.json | 76 ++++++++ .../components/prosegur/services.yaml | 2 - .../components/prosegur/strings.json | 6 + homeassistant/components/ps4/services.yaml | 6 - homeassistant/components/ps4/strings.json | 16 ++ .../components/python_script/services.yaml | 2 - .../components/python_script/strings.json | 8 + 48 files changed, 828 insertions(+), 372 deletions(-) create mode 100644 homeassistant/components/ness_alarm/strings.json create mode 100644 homeassistant/components/netgear_lte/strings.json create mode 100644 homeassistant/components/nissan_leaf/strings.json create mode 100644 homeassistant/components/nx584/strings.json create mode 100644 homeassistant/components/ombi/strings.json create mode 100644 homeassistant/components/openhome/strings.json create mode 100644 homeassistant/components/pilight/strings.json create mode 100644 homeassistant/components/ping/strings.json create mode 100644 homeassistant/components/python_script/strings.json diff --git a/homeassistant/components/neato/services.yaml b/homeassistant/components/neato/services.yaml index cbfff7808eef0e..5ec782d7bf3d66 100644 --- a/homeassistant/components/neato/services.yaml +++ b/homeassistant/components/neato/services.yaml @@ -1,14 +1,10 @@ custom_cleaning: - name: Zone Cleaning service - description: Zone Cleaning service call specific to Neato Botvacs. target: entity: integration: neato domain: vacuum fields: mode: - name: Set cleaning mode - description: "Set the cleaning mode: 1 for eco and 2 for turbo. Defaults to turbo if not set." default: 2 selector: number: @@ -16,8 +12,6 @@ custom_cleaning: max: 2 mode: box navigation: - name: Set navigation mode - description: "Set the navigation mode: 1 for normal, 2 for extra care, 3 for deep. Defaults to normal if not set." default: 1 selector: number: @@ -25,8 +19,6 @@ custom_cleaning: max: 3 mode: box category: - name: Use cleaning map - description: "Whether to use a persistent map or not for cleaning (i.e. No go lines): 2 for no map, 4 for map. Default to using map if not set (and fallback to no map if no map is found)." default: 4 selector: number: @@ -35,8 +27,6 @@ custom_cleaning: step: 2 mode: box zone: - name: Name of the zone to clean (Only Botvac D7) - description: Only supported on the Botvac D7. Name of the zone to clean. Defaults to no zone i.e. complete house cleanup. example: "Kitchen" selector: text: diff --git a/homeassistant/components/neato/strings.json b/homeassistant/components/neato/strings.json index 20848ccff08a3c..6136ac94e99e50 100644 --- a/homeassistant/components/neato/strings.json +++ b/homeassistant/components/neato/strings.json @@ -18,5 +18,29 @@ "create_entry": { "default": "[%key:common::config_flow::create_entry::authenticated%]" } + }, + "services": { + "custom_cleaning": { + "name": "Zone cleaning service", + "description": "Zone cleaning service call specific to Neato Botvacs.", + "fields": { + "mode": { + "name": "Set cleaning mode", + "description": "Set the cleaning mode: 1 for eco and 2 for turbo. Defaults to turbo if not set." + }, + "navigation": { + "name": "Set navigation mode", + "description": "Set the navigation mode: 1 for normal, 2 for extra care, 3 for deep. Defaults to normal if not set." + }, + "category": { + "name": "Use cleaning map", + "description": "Whether to use a persistent map or not for cleaning (i.e. No go lines): 2 for no map, 4 for map. Default to using map if not set (and fallback to no map if no map is found)." + }, + "zone": { + "name": "Name of the zone to clean (Only Botvac D7)", + "description": "Only supported on the Botvac D7. Name of the zone to clean. Defaults to no zone i.e. complete house cleanup." + } + } + } } } diff --git a/homeassistant/components/ness_alarm/services.yaml b/homeassistant/components/ness_alarm/services.yaml index ad320285d5b468..b02d5e368052a6 100644 --- a/homeassistant/components/ness_alarm/services.yaml +++ b/homeassistant/components/ness_alarm/services.yaml @@ -1,31 +1,21 @@ # Describes the format for available ness alarm services aux: - name: Aux - description: Trigger an aux output. fields: output_id: - name: Output ID - description: The aux output you wish to change. required: true selector: number: min: 1 max: 4 state: - name: State - description: The On/Off State. If P14xE 8E is enabled then a value of true will pulse output x for the time specified in P14(x+4)E. default: true selector: boolean: panic: - name: Panic - description: Trigger a panic fields: code: - name: Code - description: The user code to use to trigger the panic. required: true example: 1234 selector: diff --git a/homeassistant/components/ness_alarm/strings.json b/homeassistant/components/ness_alarm/strings.json new file mode 100644 index 00000000000000..ec4e39a612816d --- /dev/null +++ b/homeassistant/components/ness_alarm/strings.json @@ -0,0 +1,28 @@ +{ + "services": { + "aux": { + "name": "Aux", + "description": "Trigger an aux output.", + "fields": { + "output_id": { + "name": "Output ID", + "description": "The aux output you wish to change." + }, + "state": { + "name": "State", + "description": "The On/Off State. If P14xE 8E is enabled then a value of true will pulse output x for the time specified in P14(x+4)E." + } + } + }, + "panic": { + "name": "Panic", + "description": "Triggers a panic.", + "fields": { + "code": { + "name": "Code", + "description": "The user code to use to trigger the panic." + } + } + } + } +} diff --git a/homeassistant/components/nest/services.yaml b/homeassistant/components/nest/services.yaml index 24b7290668fb03..5f68bd6a1f2db6 100644 --- a/homeassistant/components/nest/services.yaml +++ b/homeassistant/components/nest/services.yaml @@ -1,12 +1,8 @@ # Describes the format for available Nest services set_away_mode: - name: Set away mode - description: Set the away mode for a Nest structure. fields: away_mode: - name: Away mode - description: New mode to set. required: true selector: select: @@ -14,55 +10,37 @@ set_away_mode: - "away" - "home" structure: - name: Structure - description: Name(s) of structure(s) to change. Defaults to all structures if not specified. example: "Apartment" selector: object: set_eta: - name: Set estimated time of arrival - description: Set or update the estimated time of arrival window for a Nest structure. fields: eta: - name: ETA - description: Estimated time of arrival from now. required: true selector: time: eta_window: - name: ETA window - description: Estimated time of arrival window. default: "00:01" selector: time: trip_id: - name: Trip ID - description: Unique ID for the trip. Default is auto-generated using a timestamp. example: "Leave Work" selector: text: structure: - name: Structure - description: Name(s) of structure(s) to change. Defaults to all structures if not specified. example: "Apartment" selector: object: cancel_eta: - name: Cancel ETA - description: Cancel an existing estimated time of arrival window for a Nest structure. fields: trip_id: - name: Trip ID - description: Unique ID for the trip. required: true example: "Leave Work" selector: text: structure: - name: Structure - description: Name(s) of structure(s) to change. Defaults to all structures if not specified. example: "Apartment" selector: object: diff --git a/homeassistant/components/nest/strings.json b/homeassistant/components/nest/strings.json index 86650bbbe9aa51..b6941f51392ff3 100644 --- a/homeassistant/components/nest/strings.json +++ b/homeassistant/components/nest/strings.json @@ -68,5 +68,57 @@ "title": "Legacy Works With Nest has been removed", "description": "Legacy Works With Nest has been removed from Home Assistant, and the API shuts down as of September 2023.\n\nYou must take action to use the SDM API. Remove all `nest` configuration from `configuration.yaml` and restart Home Assistant, then see the Nest [integration instructions]({documentation_url}) for set up instructions and supported devices." } + }, + "services": { + "set_away_mode": { + "name": "Set away mode", + "description": "Sets the away mode for a Nest structure.", + "fields": { + "away_mode": { + "name": "Away mode", + "description": "New mode to set." + }, + "structure": { + "name": "Structure", + "description": "Name(s) of structure(s) to change. Defaults to all structures if not specified." + } + } + }, + "set_eta": { + "name": "Set estimated time of arrival", + "description": "Sets or update the estimated time of arrival window for a Nest structure.", + "fields": { + "eta": { + "name": "ETA", + "description": "Estimated time of arrival from now." + }, + "eta_window": { + "name": "ETA window", + "description": "Estimated time of arrival window." + }, + "trip_id": { + "name": "Trip ID", + "description": "Unique ID for the trip. Default is auto-generated using a timestamp." + }, + "structure": { + "name": "Structure", + "description": "Name(s) of structure(s) to change. Defaults to all structures if not specified." + } + } + }, + "cancel_eta": { + "name": "Cancel ETA", + "description": "Cancels an existing estimated time of arrival window for a Nest structure.", + "fields": { + "trip_id": { + "name": "Trip ID", + "description": "Unique ID for the trip." + }, + "structure": { + "name": "Structure", + "description": "Name(s) of structure(s) to change. Defaults to all structures if not specified." + } + } + } } } diff --git a/homeassistant/components/netatmo/services.yaml b/homeassistant/components/netatmo/services.yaml index e61e893e19999f..726d6867d2d43b 100644 --- a/homeassistant/components/netatmo/services.yaml +++ b/homeassistant/components/netatmo/services.yaml @@ -1,15 +1,11 @@ # Describes the format for available Netatmo services set_camera_light: - name: Set camera light mode - description: Sets the light mode for a Netatmo Outdoor camera light. target: entity: integration: netatmo domain: light fields: camera_light_mode: - name: Camera light mode - description: Outdoor camera light mode. required: true selector: select: @@ -19,60 +15,39 @@ set_camera_light: - "auto" set_schedule: - name: Set heating schedule - description: - Set the heating schedule for Netatmo climate device. The schedule name must - match a schedule configured at Netatmo. target: entity: integration: netatmo domain: climate fields: schedule_name: - description: Schedule name example: Standard required: true selector: text: set_persons_home: - name: Set persons at home - description: - Set a list of persons as at home. Person's name must match a name known by - the Netatmo Indoor (Welcome) Camera. target: entity: integration: netatmo domain: camera fields: persons: - description: List of names example: "[Alice, Bob]" required: true selector: object: set_person_away: - name: Set person away - description: - Set a person as away. If no person is set the home will be marked as empty. - Person's name must match a name known by the Netatmo Indoor (Welcome) - Camera. target: entity: integration: netatmo domain: camera fields: person: - description: Person's name. example: Bob selector: text: register_webhook: - name: Register webhook - description: Register the webhook to the Netatmo backend. - unregister_webhook: - name: Unregister webhook - description: Unregister the webhook from the Netatmo backend. diff --git a/homeassistant/components/netatmo/strings.json b/homeassistant/components/netatmo/strings.json index 617d813007c5de..05d0e716ef464e 100644 --- a/homeassistant/components/netatmo/strings.json +++ b/homeassistant/components/netatmo/strings.json @@ -66,5 +66,55 @@ "cancel_set_point": "{entity_name} has resumed its schedule", "therm_mode": "{entity_name} switched to \"{subtype}\"" } + }, + "services": { + "set_camera_light": { + "name": "Set camera light mode", + "description": "Sets the light mode for a Netatmo Outdoor camera light.", + "fields": { + "camera_light_mode": { + "name": "Camera light mode", + "description": "Outdoor camera light mode." + } + } + }, + "set_schedule": { + "name": "Set heating schedule", + "description": "Sets the heating schedule for Netatmo climate device. The schedule name must match a schedule configured at Netatmo.", + "fields": { + "schedule_name": { + "name": "Schedule", + "description": "Schedule name." + } + } + }, + "set_persons_home": { + "name": "Set persons at home", + "description": "Sets a list of persons as at home. Person's name must match a name known by the Netatmo Indoor (Welcome) Camera.", + "fields": { + "persons": { + "name": "Persons", + "description": "List of names." + } + } + }, + "set_person_away": { + "name": "Set person away", + "description": "Sets a person as away. If no person is set the home will be marked as empty. Person's name must match a name known by the Netatmo Indoor (Welcome) Camera.", + "fields": { + "person": { + "name": "Person", + "description": "Person's name." + } + } + }, + "register_webhook": { + "name": "Register webhook", + "description": "Registers the webhook to the Netatmo backend." + }, + "unregister_webhook": { + "name": "Unregister webhook", + "description": "Unregisters the webhook from the Netatmo backend." + } } } diff --git a/homeassistant/components/netgear_lte/services.yaml b/homeassistant/components/netgear_lte/services.yaml index bed9647a1b7d2c..05cf8cc3c97089 100644 --- a/homeassistant/components/netgear_lte/services.yaml +++ b/homeassistant/components/netgear_lte/services.yaml @@ -1,34 +1,22 @@ delete_sms: - name: Delete SMS - description: Delete messages from the modem inbox. fields: host: - name: Host - description: The modem that should have a message deleted. example: 192.168.5.1 selector: text: sms_id: - name: SMS ID - description: Integer or list of integers with inbox IDs of messages to delete. required: true example: 7 selector: object: set_option: - name: Set option - description: Set options on the modem. fields: host: - name: Host - description: The modem to set options on. example: 192.168.5.1 selector: text: failover: - name: Failover - description: Failover mode. selector: select: options: @@ -36,8 +24,6 @@ set_option: - "mobile" - "wire" autoconnect: - name: Auto-connect - description: Auto-connect mode. selector: select: options: @@ -46,22 +32,15 @@ set_option: - "never" connect_lte: - name: Connect LTE - description: Ask the modem to establish the LTE connection. fields: host: - name: Host - description: The modem that should connect. example: 192.168.5.1 selector: text: disconnect_lte: - name: Disconnect LTE - description: Ask the modem to close the LTE connection. fields: host: - description: The modem that should disconnect. example: 192.168.5.1 selector: text: diff --git a/homeassistant/components/netgear_lte/strings.json b/homeassistant/components/netgear_lte/strings.json new file mode 100644 index 00000000000000..9c4c67bddf7ba1 --- /dev/null +++ b/homeassistant/components/netgear_lte/strings.json @@ -0,0 +1,57 @@ +{ + "services": { + "delete_sms": { + "name": "Delete SMS", + "description": "Deletes messages from the modem inbox.", + "fields": { + "host": { + "name": "Host", + "description": "The modem that should have a message deleted." + }, + "sms_id": { + "name": "SMS ID", + "description": "Integer or list of integers with inbox IDs of messages to delete." + } + } + }, + "set_option": { + "name": "Set option", + "description": "Sets options on the modem.", + "fields": { + "host": { + "name": "Host", + "description": "The modem to set options on." + }, + "failover": { + "name": "Failover", + "description": "Failover mode." + }, + "autoconnect": { + "name": "Auto-connect", + "description": "Auto-connect mode." + } + } + }, + "connect_lte": { + "name": "Connect LTE", + "description": "Asks the modem to establish the LTE connection.", + "fields": { + "host": { + "name": "Host", + "description": "The modem that should connect." + } + } + }, + "disconnect_lte": { + "name": "Disconnect LTE", + "description": "Asks the modem to close the LTE connection.", + "fields": { + "host": { + "name": "Host", + "description": "The modem that should disconnect." + } + } + } + }, + "selector": {} +} diff --git a/homeassistant/components/nexia/services.yaml b/homeassistant/components/nexia/services.yaml index 0deb5225cd3985..ede1f311acf34a 100644 --- a/homeassistant/components/nexia/services.yaml +++ b/homeassistant/components/nexia/services.yaml @@ -1,14 +1,10 @@ set_aircleaner_mode: - name: Set air cleaner mode - description: "The air cleaner mode." target: entity: integration: nexia domain: climate fields: aircleaner_mode: - name: Air cleaner mode - description: "The air cleaner mode to set." required: true selector: select: @@ -18,16 +14,12 @@ set_aircleaner_mode: - "quick" set_humidify_setpoint: - name: Set humidify set point - description: "The humidification set point." target: entity: integration: nexia domain: climate fields: humidity: - name: Humidify - description: "The humidification setpoint." required: true selector: number: @@ -36,16 +28,12 @@ set_humidify_setpoint: unit_of_measurement: "%" set_hvac_run_mode: - name: Set hvac run mode - description: "The hvac run mode." target: entity: integration: nexia domain: climate fields: run_mode: - name: Run mode - description: "Run the schedule or hold. If not specified, the current run mode will be used." required: false selector: select: @@ -53,8 +41,6 @@ set_hvac_run_mode: - "permanent_hold" - "run_schedule" hvac_mode: - name: Hvac mode - description: "The hvac mode to use for the schedule or hold. If not specified, the current hvac mode will be used." required: false selector: select: diff --git a/homeassistant/components/nexia/strings.json b/homeassistant/components/nexia/strings.json index c9bc84243da819..f3d343ffda32ec 100644 --- a/homeassistant/components/nexia/strings.json +++ b/homeassistant/components/nexia/strings.json @@ -17,5 +17,41 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" } + }, + "services": { + "set_aircleaner_mode": { + "name": "Set air cleaner mode", + "description": "The air cleaner mode.", + "fields": { + "aircleaner_mode": { + "name": "Air cleaner mode", + "description": "The air cleaner mode to set." + } + } + }, + "set_humidify_setpoint": { + "name": "Set humidify set point", + "description": "The humidification set point.", + "fields": { + "humidity": { + "name": "Humidify", + "description": "The humidification setpoint." + } + } + }, + "set_hvac_run_mode": { + "name": "Set hvac run mode", + "description": "The HVAC run mode.", + "fields": { + "run_mode": { + "name": "Run mode", + "description": "Run the schedule or hold. If not specified, the current run mode will be used." + }, + "hvac_mode": { + "name": "HVAC mode", + "description": "The HVAC mode to use for the schedule or hold. If not specified, the current HVAC mode will be used." + } + } + } } } diff --git a/homeassistant/components/nissan_leaf/services.yaml b/homeassistant/components/nissan_leaf/services.yaml index 901e70de414fbb..d49480726679de 100644 --- a/homeassistant/components/nissan_leaf/services.yaml +++ b/homeassistant/components/nissan_leaf/services.yaml @@ -1,29 +1,16 @@ # Describes the format for available services for nissan_leaf start_charge: - name: Start charge - description: > - Start the vehicle charging. It must be plugged in first! fields: vin: - name: VIN - description: > - The vehicle identification number (VIN) of the vehicle, 17 characters required: true example: WBANXXXXXX1234567 selector: text: update: - name: Update - description: > - Fetch the last state of the vehicle of all your accounts, requesting - an update from of the state from the car if possible. fields: vin: - name: VIN - description: > - The vehicle identification number (VIN) of the vehicle, 17 characters required: true example: WBANXXXXXX1234567 selector: diff --git a/homeassistant/components/nissan_leaf/strings.json b/homeassistant/components/nissan_leaf/strings.json new file mode 100644 index 00000000000000..4dae6cb898b784 --- /dev/null +++ b/homeassistant/components/nissan_leaf/strings.json @@ -0,0 +1,24 @@ +{ + "services": { + "start_charge": { + "name": "Start charge", + "description": "Starts the vehicle charging. It must be plugged in first!\n.", + "fields": { + "vin": { + "name": "VIN", + "description": "The vehicle identification number (VIN) of the vehicle, 17 characters\n." + } + } + }, + "update": { + "name": "Update", + "description": "Fetches the last state of the vehicle of all your accounts, requesting an update from of the state from the car if possible.\n.", + "fields": { + "vin": { + "name": "VIN", + "description": "The vehicle identification number (VIN) of the vehicle, 17 characters\n." + } + } + } + } +} diff --git a/homeassistant/components/nuki/services.yaml b/homeassistant/components/nuki/services.yaml index c43f081dbf73c5..2002ab8614a7e6 100644 --- a/homeassistant/components/nuki/services.yaml +++ b/homeassistant/components/nuki/services.yaml @@ -1,28 +1,20 @@ lock_n_go: - name: Lock 'n' go - description: "Nuki Lock 'n' Go" target: entity: integration: nuki domain: lock fields: unlatch: - name: Unlatch - description: Whether to unlatch the lock. default: false selector: boolean: set_continuous_mode: - name: Set Continuous Mode - description: "Enable or disable Continuous Mode on Nuki Opener" target: entity: integration: nuki domain: lock fields: enable: - name: Enable - description: Whether to enable or disable the feature default: false selector: boolean: diff --git a/homeassistant/components/nuki/strings.json b/homeassistant/components/nuki/strings.json index 4629f6a2a3b534..68ab508141b378 100644 --- a/homeassistant/components/nuki/strings.json +++ b/homeassistant/components/nuki/strings.json @@ -45,5 +45,27 @@ } } } + }, + "services": { + "lock_n_go": { + "name": "Lock 'n' go", + "description": "Nuki Lock 'n' Go.", + "fields": { + "unlatch": { + "name": "Unlatch", + "description": "Whether to unlatch the lock." + } + } + }, + "set_continuous_mode": { + "name": "Set continuous code", + "description": "Enables or disables continuous mode on Nuki Opener.", + "fields": { + "enable": { + "name": "Enable", + "description": "Whether to enable or disable the feature." + } + } + } } } diff --git a/homeassistant/components/nx584/services.yaml b/homeassistant/components/nx584/services.yaml index a5c49f6d6a6bdb..da5c0638a4fe1e 100644 --- a/homeassistant/components/nx584/services.yaml +++ b/homeassistant/components/nx584/services.yaml @@ -1,16 +1,12 @@ # Describes the format for available nx584 services bypass_zone: - name: Bypass zone - description: Bypass a zone. target: entity: integration: nx584 domain: alarm_control_panel fields: zone: - name: Zone - description: The number of the zone to be bypassed. required: true selector: number: @@ -18,16 +14,12 @@ bypass_zone: max: 255 unbypass_zone: - name: Un-bypass zone - description: Un-Bypass a zone. target: entity: integration: nx584 domain: alarm_control_panel fields: zone: - name: Zone - description: The number of the zone to be un-bypassed. required: true selector: number: diff --git a/homeassistant/components/nx584/strings.json b/homeassistant/components/nx584/strings.json new file mode 100644 index 00000000000000..11f94e7a72c538 --- /dev/null +++ b/homeassistant/components/nx584/strings.json @@ -0,0 +1,24 @@ +{ + "services": { + "bypass_zone": { + "name": "Bypass zone", + "description": "Bypasses a zone.", + "fields": { + "zone": { + "name": "Zone", + "description": "The number of the zone to be bypassed." + } + } + }, + "unbypass_zone": { + "name": "Un-bypass zone", + "description": "Un-Bypasses a zone.", + "fields": { + "zone": { + "name": "Zone", + "description": "The number of the zone to be un-bypassed." + } + } + } + } +} diff --git a/homeassistant/components/nzbget/services.yaml b/homeassistant/components/nzbget/services.yaml index 46439b761e1c28..0131bb6ae3a336 100644 --- a/homeassistant/components/nzbget/services.yaml +++ b/homeassistant/components/nzbget/services.yaml @@ -1,20 +1,10 @@ # Describes the format for available nzbget services pause: - name: Pause - description: Pause download queue. - resume: - name: Resume - description: Resume download queue. - set_speed: - name: Set speed - description: Set download speed limit fields: speed: - name: Speed - description: Speed limit. 0 is unlimited. default: 1000 selector: number: diff --git a/homeassistant/components/nzbget/strings.json b/homeassistant/components/nzbget/strings.json index fc7d8508a1225f..5a96d2f8951cf6 100644 --- a/homeassistant/components/nzbget/strings.json +++ b/homeassistant/components/nzbget/strings.json @@ -31,5 +31,25 @@ } } } + }, + "services": { + "pause": { + "name": "Pause", + "description": "Pauses download queue." + }, + "resume": { + "name": "Resume", + "description": "Resumes download queue." + }, + "set_speed": { + "name": "Set speed", + "description": "Sets download speed limit.", + "fields": { + "speed": { + "name": "Speed", + "description": "Speed limit. 0 is unlimited." + } + } + } } } diff --git a/homeassistant/components/ombi/services.yaml b/homeassistant/components/ombi/services.yaml index d7e7068e84c1e9..8803d2788bf4e3 100644 --- a/homeassistant/components/ombi/services.yaml +++ b/homeassistant/components/ombi/services.yaml @@ -1,30 +1,20 @@ # Ombi services.yaml entries submit_movie_request: - name: Sumbit movie request - description: Searches for a movie and requests the first result. fields: name: - name: Name - description: Search parameter required: true example: "beverly hills cop" selector: text: submit_tv_request: - name: Submit tv request - description: Searches for a TV show and requests the first result. fields: name: - name: Name - description: Search parameter required: true example: "breaking bad" selector: text: season: - name: Season - description: Which season(s) to request. default: latest selector: select: @@ -34,12 +24,8 @@ submit_tv_request: - "latest" submit_music_request: - name: Submit music request - description: Searches for a music album and requests the first result. fields: name: - name: Name - description: Search parameter required: true example: "nevermind" selector: diff --git a/homeassistant/components/ombi/strings.json b/homeassistant/components/ombi/strings.json new file mode 100644 index 00000000000000..70a3767c889e97 --- /dev/null +++ b/homeassistant/components/ombi/strings.json @@ -0,0 +1,38 @@ +{ + "services": { + "submit_movie_request": { + "name": "Sumbit movie request", + "description": "Searches for a movie and requests the first result.", + "fields": { + "name": { + "name": "Name", + "description": "Search parameter." + } + } + }, + "submit_tv_request": { + "name": "Submit TV request", + "description": "Searches for a TV show and requests the first result.", + "fields": { + "name": { + "name": "Name", + "description": "Search parameter." + }, + "season": { + "name": "Season", + "description": "Which season(s) to request." + } + } + }, + "submit_music_request": { + "name": "Submit music request", + "description": "Searches for a music album and requests the first result.", + "fields": { + "name": { + "name": "Name", + "description": "Search parameter." + } + } + } + } +} diff --git a/homeassistant/components/omnilogic/services.yaml b/homeassistant/components/omnilogic/services.yaml index 94ba0d2982ef7f..c82ea7ebbbf427 100644 --- a/homeassistant/components/omnilogic/services.yaml +++ b/homeassistant/components/omnilogic/services.yaml @@ -1,14 +1,10 @@ set_pump_speed: - name: Set pump speed - description: Set the run speed of a variable speed pump. target: entity: integration: omnilogic domain: switch fields: speed: - name: Speed - description: Speed for the VSP between min and max speed. required: true selector: number: diff --git a/homeassistant/components/omnilogic/strings.json b/homeassistant/components/omnilogic/strings.json index 2bbb927fd27734..454644be244329 100644 --- a/homeassistant/components/omnilogic/strings.json +++ b/homeassistant/components/omnilogic/strings.json @@ -27,5 +27,17 @@ } } } + }, + "services": { + "set_pump_speed": { + "name": "Set pump speed", + "description": "Sets the run speed of a variable speed pump.", + "fields": { + "speed": { + "name": "Speed", + "description": "Speed for the VSP between min and max speed." + } + } + } } } diff --git a/homeassistant/components/onvif/services.yaml b/homeassistant/components/onvif/services.yaml index 9d753b2fe77b4d..9cf3a1fc4c17ae 100644 --- a/homeassistant/components/onvif/services.yaml +++ b/homeassistant/components/onvif/services.yaml @@ -1,38 +1,28 @@ ptz: - name: PTZ - description: If your ONVIF camera supports PTZ, you will be able to pan, tilt or zoom your camera. target: entity: integration: onvif domain: camera fields: tilt: - name: Tilt - description: "Tilt direction." selector: select: options: - "DOWN" - "UP" pan: - name: Pan - description: "Pan direction." selector: select: options: - "LEFT" - "RIGHT" zoom: - name: Zoom - description: "Zoom." selector: select: options: - "ZOOM_IN" - "ZOOM_OUT" distance: - name: Distance - description: "Distance coefficient. Sets how much PTZ should be executed in one request." default: 0.1 selector: number: @@ -40,8 +30,6 @@ ptz: max: 1 step: 0.01 speed: - name: Speed - description: "Speed coefficient. Sets how fast PTZ will be executed." default: 0.5 selector: number: @@ -49,8 +37,6 @@ ptz: max: 1 step: 0.01 continuous_duration: - name: Continuous duration - description: "Set ContinuousMove delay in seconds before stopping the move" default: 0.5 selector: number: @@ -58,15 +44,11 @@ ptz: max: 1 step: 0.01 preset: - name: Preset - description: "PTZ preset profile token. Sets the preset profile token which is executed with GotoPreset" example: "1" default: "0" selector: text: move_mode: - name: Move Mode - description: "PTZ moving mode." default: "RelativeMove" selector: select: diff --git a/homeassistant/components/onvif/strings.json b/homeassistant/components/onvif/strings.json index 8e989f1dfa098b..cabab347264bf9 100644 --- a/homeassistant/components/onvif/strings.json +++ b/homeassistant/components/onvif/strings.json @@ -67,5 +67,45 @@ "title": "ONVIF Device Options" } } + }, + "services": { + "ptz": { + "name": "PTZ", + "description": "If your ONVIF camera supports PTZ, you will be able to pan, tilt or zoom your camera.", + "fields": { + "tilt": { + "name": "Tilt", + "description": "Tilt direction." + }, + "pan": { + "name": "Pan", + "description": "Pan direction." + }, + "zoom": { + "name": "Zoom", + "description": "Zoom." + }, + "distance": { + "name": "Distance", + "description": "Distance coefficient. Sets how much PTZ should be executed in one request." + }, + "speed": { + "name": "Speed", + "description": "Speed coefficient. Sets how fast PTZ will be executed." + }, + "continuous_duration": { + "name": "Continuous duration", + "description": "Set ContinuousMove delay in seconds before stopping the move." + }, + "preset": { + "name": "Preset", + "description": "PTZ preset profile token. Sets the preset profile token which is executed with GotoPreset." + }, + "move_mode": { + "name": "Move Mode", + "description": "PTZ moving mode." + } + } + } } } diff --git a/homeassistant/components/openhome/services.yaml b/homeassistant/components/openhome/services.yaml index 0fa951452872bf..7ccba4fb497876 100644 --- a/homeassistant/components/openhome/services.yaml +++ b/homeassistant/components/openhome/services.yaml @@ -1,16 +1,12 @@ # Describes the format for available openhome services invoke_pin: - name: Invoke PIN - description: Invoke a pin on the specified device. target: entity: integration: openhome domain: media_player fields: pin: - name: PIN - description: Which pin to invoke required: true selector: number: diff --git a/homeassistant/components/openhome/strings.json b/homeassistant/components/openhome/strings.json new file mode 100644 index 00000000000000..b13fb997b7f89c --- /dev/null +++ b/homeassistant/components/openhome/strings.json @@ -0,0 +1,14 @@ +{ + "services": { + "invoke_pin": { + "name": "Invoke PIN", + "description": "Invokes a pin on the specified device.", + "fields": { + "pin": { + "name": "PIN", + "description": "Which pin to invoke." + } + } + } + } +} diff --git a/homeassistant/components/opentherm_gw/services.yaml b/homeassistant/components/opentherm_gw/services.yaml index 77ef501f9d87e6..d68624e07630d7 100644 --- a/homeassistant/components/opentherm_gw/services.yaml +++ b/homeassistant/components/opentherm_gw/services.yaml @@ -1,84 +1,49 @@ # Describes the format for available opentherm_gw services reset_gateway: - name: Reset gateway - description: Reset the OpenTherm Gateway. fields: gateway_id: - name: Gateway ID - description: The gateway_id of the OpenTherm Gateway. required: true example: "opentherm_gateway" selector: text: set_central_heating_ovrd: - name: Set central heating override - description: > - Set the central heating override option on the gateway. - When overriding the control setpoint (via a set_control_setpoint service call with a value other than 0), the gateway automatically enables the central heating override to start heating. - This service can then be used to control the central heating override status. - To return control of the central heating to the thermostat, call the set_control_setpoint service with temperature value 0. - You will only need this if you are writing your own software thermostat. fields: gateway_id: - name: Gateway ID - description: The gateway_id of the OpenTherm Gateway. required: true example: "opentherm_gateway" selector: text: ch_override: - name: Central heating override - description: > - The desired boolean value for the central heating override. required: true selector: boolean: set_clock: - name: Set clock - description: Set the clock and day of the week on the connected thermostat. fields: gateway_id: - name: Gateway ID - description: The gateway_id of the OpenTherm Gateway. required: true example: "opentherm_gateway" selector: text: date: - name: Date - description: Optional date from which the day of the week will be extracted. Defaults to today. example: "2018-10-23" selector: text: time: - name: Time - description: Optional time in 24h format which will be provided to the thermostat. Defaults to the current time. example: "19:34" selector: text: set_control_setpoint: - name: Set control set point - description: > - Set the central heating control setpoint override on the gateway. - You will only need this if you are writing your own software thermostat. fields: gateway_id: - name: Gateway ID - description: The gateway_id of the OpenTherm Gateway. required: true example: "opentherm_gateway" selector: text: temperature: - name: Temperature - description: > - The central heating setpoint to set on the gateway. - Values between 0 and 90 are accepted, but not all boilers support this range. - A value of 0 disables the central heating setpoint override. required: true selector: number: @@ -88,49 +53,26 @@ set_control_setpoint: unit_of_measurement: "°" set_hot_water_ovrd: - name: Set hot water override - description: > - Set the domestic hot water enable option on the gateway. fields: gateway_id: - name: Gateway ID - description: The gateway_id of the OpenTherm Gateway. required: true example: "opentherm_gateway" selector: text: dhw_override: - name: Domestic hot water override - description: > - Control the domestic hot water enable option. If the boiler has - been configured to let the room unit control when to keep a - small amount of water preheated, this command can influence - that. - Value should be 0 or 1 to enable the override in off or on - state, or "A" to disable the override. required: true example: "1" selector: text: set_hot_water_setpoint: - name: Set hot water set point - description: > - Set the domestic hot water setpoint on the gateway. fields: gateway_id: - name: Gateway ID - description: The gateway_id of the OpenTherm Gateway. required: true example: "opentherm_gateway" selector: text: temperature: - name: Temperature - description: > - The domestic hot water setpoint to set on the gateway. Not all boilers support this feature. - Values between 0 and 90 are accepted, but not all boilers support this range. - Check the values of the slave_dhw_min_setp and slave_dhw_max_setp sensors to see the supported range on your boiler. selector: number: min: 0 @@ -139,19 +81,13 @@ set_hot_water_setpoint: unit_of_measurement: "°" set_gpio_mode: - name: Set gpio mode - description: Change the function of the GPIO pins of the gateway. fields: gateway_id: - name: Gateway ID - description: The gateway_id of the OpenTherm Gateway. required: true example: "opentherm_gateway" selector: text: id: - name: ID - description: The ID of the GPIO pin. required: true selector: select: @@ -159,10 +95,6 @@ set_gpio_mode: - "A" - "B" mode: - name: Mode - description: > - Mode to set on the GPIO pin. Values 0 through 6 are accepted for both GPIOs, 7 is only accepted for GPIO "B". - See https://www.home-assistant.io/integrations/opentherm_gw/#gpio-modes for an explanation of the values. required: true selector: number: @@ -170,19 +102,13 @@ set_gpio_mode: max: 7 set_led_mode: - name: Set LED mode - description: Change the function of the LEDs of the gateway. fields: gateway_id: - name: Gateway ID - description: The gateway_id of the OpenTherm Gateway. required: true example: "opentherm_gateway" selector: text: id: - name: ID - description: The ID of the LED. required: true selector: select: @@ -194,10 +120,6 @@ set_led_mode: - "E" - "F" mode: - name: Mode - description: > - The function to assign to the LED. - See https://www.home-assistant.io/integrations/opentherm_gw/#led-modes for an explanation of the values. required: true selector: select: @@ -216,23 +138,13 @@ set_led_mode: - "X" set_max_modulation: - name: Set max modulation - description: > - Override the maximum relative modulation level. - You will only need this if you are writing your own software thermostat. fields: gateway_id: - name: Gateway ID - description: The gateway_id of the OpenTherm Gateway. required: true example: "opentherm_gateway" selector: text: level: - name: Level - description: > - The modulation level to provide to the gateway. - Provide a value of -1 to clear the override and forward the value from the thermostat again. required: true selector: number: @@ -240,24 +152,13 @@ set_max_modulation: max: 100 set_outside_temperature: - name: Set outside temperature - description: > - Provide an outside temperature to the thermostat. - If your thermostat is unable to display an outside temperature and does not support OTC (Outside Temperature Correction), this has no effect. fields: gateway_id: - name: Gateway ID - description: The gateway_id of the OpenTherm Gateway. required: true example: "opentherm_gateway" selector: text: temperature: - name: Temperature - description: > - The temperature to provide to the thermostat. - Values between -40.0 and 64.0 will be accepted, but not all thermostats can display the full range. - Any value above 64.0 will clear a previously configured value (suggestion: 99) required: true selector: number: @@ -266,19 +167,13 @@ set_outside_temperature: unit_of_measurement: "°" set_setback_temperature: - name: Set setback temperature - description: Configure the setback temperature to be used with the GPIO away mode function. fields: gateway_id: - name: Gateway ID - description: The gateway_id of the OpenTherm Gateway. required: true example: "opentherm_gateway" selector: text: temperature: - name: Temperature - description: The setback temperature to configure on the gateway. required: true selector: number: diff --git a/homeassistant/components/opentherm_gw/strings.json b/homeassistant/components/opentherm_gw/strings.json index a80a059481dcfe..d23fe1c09246d4 100644 --- a/homeassistant/components/opentherm_gw/strings.json +++ b/homeassistant/components/opentherm_gw/strings.json @@ -27,5 +27,169 @@ } } } + }, + "services": { + "reset_gateway": { + "name": "Reset gateway", + "description": "Resets the OpenTherm Gateway.", + "fields": { + "gateway_id": { + "name": "Gateway ID", + "description": "The gateway_id of the OpenTherm Gateway." + } + } + }, + "set_central_heating_ovrd": { + "name": "Set central heating override", + "description": "Sets the central heating override option on the gateway. When overriding the control setpoint (via a set_control_setpoint service call with a value other than 0), the gateway automatically enables the central heating override to start heating. This service can then be used to control the central heating override status. To return control of the central heating to the thermostat, call the set_control_setpoint service with temperature value 0. You will only need this if you are writing your own software thermostat.\n.", + "fields": { + "gateway_id": { + "name": "Gateway ID", + "description": "The gateway_id of the OpenTherm Gateway." + }, + "ch_override": { + "name": "Central heating override", + "description": "The desired boolean value for the central heating override." + } + } + }, + "set_clock": { + "name": "Set clock", + "description": "Sets the clock and day of the week on the connected thermostat.", + "fields": { + "gateway_id": { + "name": "Gateway ID", + "description": "The gateway_id of the OpenTherm Gateway." + }, + "date": { + "name": "Date", + "description": "Optional date from which the day of the week will be extracted. Defaults to today." + }, + "time": { + "name": "Time", + "description": "Optional time in 24h format which will be provided to the thermostat. Defaults to the current time." + } + } + }, + "set_control_setpoint": { + "name": "Set control set point", + "description": "Sets the central heating control setpoint override on the gateway. You will only need this if you are writing your own software thermostat.\n.", + "fields": { + "gateway_id": { + "name": "Gateway ID", + "description": "The gateway_id of the OpenTherm Gateway." + }, + "temperature": { + "name": "Temperature", + "description": "The central heating setpoint to set on the gateway. Values between 0 and 90 are accepted, but not all boilers support this range. A value of 0 disables the central heating setpoint override.\n." + } + } + }, + "set_hot_water_ovrd": { + "name": "Set hot water override", + "description": "Sets the domestic hot water enable option on the gateway.", + "fields": { + "gateway_id": { + "name": "Gateway ID", + "description": "The gateway_id of the OpenTherm Gateway." + }, + "dhw_override": { + "name": "Domestic hot water override", + "description": "Control the domestic hot water enable option. If the boiler has been configured to let the room unit control when to keep a small amount of water preheated, this command can influence that. Value should be 0 or 1 to enable the override in off or on state, or \"A\" to disable the override.\n." + } + } + }, + "set_hot_water_setpoint": { + "name": "Set hot water set point", + "description": "Sets the domestic hot water setpoint on the gateway.", + "fields": { + "gateway_id": { + "name": "Gateway ID", + "description": "The gateway_id of the OpenTherm Gateway." + }, + "temperature": { + "name": "Temperature", + "description": "The domestic hot water setpoint to set on the gateway. Not all boilers support this feature. Values between 0 and 90 are accepted, but not all boilers support this range. Check the values of the slave_dhw_min_setp and slave_dhw_max_setp sensors to see the supported range on your boiler.\n." + } + } + }, + "set_gpio_mode": { + "name": "Set gpio mode", + "description": "Changes the function of the GPIO pins of the gateway.", + "fields": { + "gateway_id": { + "name": "Gateway ID", + "description": "The gateway_id of the OpenTherm Gateway." + }, + "id": { + "name": "ID", + "description": "The ID of the GPIO pin." + }, + "mode": { + "name": "Mode", + "description": "Mode to set on the GPIO pin. Values 0 through 6 are accepted for both GPIOs, 7 is only accepted for GPIO \"B\". See https://www.home-assistant.io/integrations/opentherm_gw/#gpio-modes for an explanation of the values.\n." + } + } + }, + "set_led_mode": { + "name": "Set LED mode", + "description": "Changes the function of the LEDs of the gateway.", + "fields": { + "gateway_id": { + "name": "Gateway ID", + "description": "The gateway_id of the OpenTherm Gateway." + }, + "id": { + "name": "ID", + "description": "The ID of the LED." + }, + "mode": { + "name": "Mode", + "description": "The function to assign to the LED. See https://www.home-assistant.io/integrations/opentherm_gw/#led-modes for an explanation of the values.\n." + } + } + }, + "set_max_modulation": { + "name": "Set max modulation", + "description": "Overrides the maximum relative modulation level. You will only need this if you are writing your own software thermostat.\n.", + "fields": { + "gateway_id": { + "name": "Gateway ID", + "description": "The gateway_id of the OpenTherm Gateway." + }, + "level": { + "name": "Level", + "description": "The modulation level to provide to the gateway. Provide a value of -1 to clear the override and forward the value from the thermostat again.\n." + } + } + }, + "set_outside_temperature": { + "name": "Set outside temperature", + "description": "Provides an outside temperature to the thermostat. If your thermostat is unable to display an outside temperature and does not support OTC (Outside Temperature Correction), this has no effect.\n.", + "fields": { + "gateway_id": { + "name": "Gateway ID", + "description": "The gateway_id of the OpenTherm Gateway." + }, + "temperature": { + "name": "Temperature", + "description": "The temperature to provide to the thermostat. Values between -40.0 and 64.0 will be accepted, but not all thermostats can display the full range. Any value above 64.0 will clear a previously configured value (suggestion: 99)\n." + } + } + }, + "set_setback_temperature": { + "name": "Set setback temperature", + "description": "Configures the setback temperature to be used with the GPIO away mode function.", + "fields": { + "gateway_id": { + "name": "Gateway ID", + "description": "The gateway_id of the OpenTherm Gateway." + }, + "temperature": { + "name": "Temperature", + "description": "The setback temperature to configure on the gateway." + } + } + } } } diff --git a/homeassistant/components/pi_hole/services.yaml b/homeassistant/components/pi_hole/services.yaml index 1b5da9f0d4fe73..9c8d8921b128eb 100644 --- a/homeassistant/components/pi_hole/services.yaml +++ b/homeassistant/components/pi_hole/services.yaml @@ -1,14 +1,10 @@ disable: - name: Disable - description: Disable configured Pi-hole(s) for an amount of time target: entity: integration: pi_hole domain: switch fields: duration: - name: Duration - description: Time that the Pi-hole should be disabled for required: true example: "00:00:15" selector: diff --git a/homeassistant/components/pi_hole/strings.json b/homeassistant/components/pi_hole/strings.json index eb12811722bc98..1ed271931c36bf 100644 --- a/homeassistant/components/pi_hole/strings.json +++ b/homeassistant/components/pi_hole/strings.json @@ -35,23 +35,61 @@ }, "entity": { "binary_sensor": { - "status": { "name": "Status" } + "status": { + "name": "Status" + } }, "sensor": { - "ads_blocked_today": { "name": "Ads blocked today" }, - "ads_percentage_today": { "name": "Ads percentage blocked today" }, - "clients_ever_seen": { "name": "Seen clients" }, - "dns_queries_today": { "name": "DNS queries today" }, - "domains_being_blocked": { "name": "Domains blocked" }, - "queries_cached": { "name": "DNS queries cached" }, - "queries_forwarded": { "name": "DNS queries forwarded" }, - "unique_clients": { "name": "DNS unique clients" }, - "unique_domains": { "name": "DNS unique domains" } + "ads_blocked_today": { + "name": "Ads blocked today" + }, + "ads_percentage_today": { + "name": "Ads percentage blocked today" + }, + "clients_ever_seen": { + "name": "Seen clients" + }, + "dns_queries_today": { + "name": "DNS queries today" + }, + "domains_being_blocked": { + "name": "Domains blocked" + }, + "queries_cached": { + "name": "DNS queries cached" + }, + "queries_forwarded": { + "name": "DNS queries forwarded" + }, + "unique_clients": { + "name": "DNS unique clients" + }, + "unique_domains": { + "name": "DNS unique domains" + } }, "update": { - "core_update_available": { "name": "Core update available" }, - "ftl_update_available": { "name": "FTL update available" }, - "web_update_available": { "name": "Web update available" } + "core_update_available": { + "name": "Core update available" + }, + "ftl_update_available": { + "name": "FTL update available" + }, + "web_update_available": { + "name": "Web update available" + } + } + }, + "services": { + "disable": { + "name": "Disable", + "description": "Disables configured Pi-hole(s) for an amount of time.", + "fields": { + "duration": { + "name": "Duration", + "description": "Time that the Pi-hole should be disabled for." + } + } } } } diff --git a/homeassistant/components/picnic/services.yaml b/homeassistant/components/picnic/services.yaml index 9af2cb4829118e..e7afe71bb31fd1 100644 --- a/homeassistant/components/picnic/services.yaml +++ b/homeassistant/components/picnic/services.yaml @@ -1,34 +1,21 @@ add_product: - name: Add a product to the cart - description: >- - Adds a product to the cart based on a search string or product ID. - The search string and product ID are exclusive. - fields: config_entry_id: - name: Picnic service - description: The product will be added to the selected service. required: true selector: config_entry: integration: picnic product_id: - name: Product ID - description: The product ID of a Picnic product. required: false example: "10510201" selector: text: product_name: - name: Product name - description: Search for a product and add the first result required: false example: "Yoghurt" selector: text: amount: - name: Amount - description: Amount to add of the selected product required: false default: 1 selector: diff --git a/homeassistant/components/picnic/strings.json b/homeassistant/components/picnic/strings.json index f0e0d93231c1de..0fd107609d1287 100644 --- a/homeassistant/components/picnic/strings.json +++ b/homeassistant/components/picnic/strings.json @@ -71,5 +71,29 @@ "name": "End of next delivery's slot" } } + }, + "services": { + "add_product": { + "name": "Add a product to the cart", + "description": "Adds a product to the cart based on a search string or product ID. The search string and product ID are exclusive.", + "fields": { + "config_entry_id": { + "name": "Picnic service", + "description": "The product will be added to the selected service." + }, + "product_id": { + "name": "Product ID", + "description": "The product ID of a Picnic product." + }, + "product_name": { + "name": "Product name", + "description": "Search for a product and add the first result." + }, + "amount": { + "name": "Amount", + "description": "Amount to add of the selected product." + } + } + } } } diff --git a/homeassistant/components/pilight/services.yaml b/homeassistant/components/pilight/services.yaml index 6dc052043bf97c..b877ae88b0a994 100644 --- a/homeassistant/components/pilight/services.yaml +++ b/homeassistant/components/pilight/services.yaml @@ -1,10 +1,6 @@ send: - name: Send - description: Send RF code to Pilight device fields: protocol: - name: Protocol - description: "Protocol that Pilight recognizes. See https://manual.pilight.org/protocols/index.html for supported protocols and additional parameters that each protocol supports" required: true example: "lirc" selector: diff --git a/homeassistant/components/pilight/strings.json b/homeassistant/components/pilight/strings.json new file mode 100644 index 00000000000000..4cd819859a3ffa --- /dev/null +++ b/homeassistant/components/pilight/strings.json @@ -0,0 +1,14 @@ +{ + "services": { + "send": { + "name": "Send", + "description": "Sends RF code to Pilight device.", + "fields": { + "protocol": { + "name": "Protocol", + "description": "Protocol that Pilight recognizes. See https://manual.pilight.org/protocols/index.html for supported protocols and additional parameters that each protocol supports." + } + } + } + } +} diff --git a/homeassistant/components/ping/services.yaml b/homeassistant/components/ping/services.yaml index 1f7e523e6851d6..c983a105c93977 100644 --- a/homeassistant/components/ping/services.yaml +++ b/homeassistant/components/ping/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload all ping entities. diff --git a/homeassistant/components/ping/strings.json b/homeassistant/components/ping/strings.json new file mode 100644 index 00000000000000..2bd9229b607973 --- /dev/null +++ b/homeassistant/components/ping/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "reload": { + "name": "Reload", + "description": "Reloads ping sensors from the YAML-configuration." + } + } +} diff --git a/homeassistant/components/plex/services.yaml b/homeassistant/components/plex/services.yaml index 782a4d17c189f7..5ed655b7d78ad7 100644 --- a/homeassistant/components/plex/services.yaml +++ b/homeassistant/components/plex/services.yaml @@ -1,21 +1,13 @@ refresh_library: - name: Refresh library - description: Refresh a Plex library to scan for new and updated media. fields: server_name: - name: Server name - description: Name of a Plex server if multiple Plex servers configured. example: "My Plex Server" selector: text: library_name: - name: Library name - description: Name of the Plex library to refresh. required: true example: "TV Shows" selector: text: scan_for_clients: - name: Scan for clients - description: Scan for available clients from the Plex server(s), local network, and plex.tv. diff --git a/homeassistant/components/plex/strings.json b/homeassistant/components/plex/strings.json index f08b6f598623dc..9cba83653fd1ad 100644 --- a/homeassistant/components/plex/strings.json +++ b/homeassistant/components/plex/strings.json @@ -56,5 +56,25 @@ } } } + }, + "services": { + "refresh_library": { + "name": "Refresh library", + "description": "Refreshes a Plex library to scan for new and updated media.", + "fields": { + "server_name": { + "name": "Server name", + "description": "Name of a Plex server if multiple Plex servers configured." + }, + "library_name": { + "name": "Library name", + "description": "Name of the Plex library to refresh." + } + } + }, + "scan_for_clients": { + "name": "Scan for clients", + "description": "Scans for available clients from the Plex server(s), local network, and plex.tv." + } } } diff --git a/homeassistant/components/profiler/services.yaml b/homeassistant/components/profiler/services.yaml index 3bd6d7636ac6f1..311325fa404a1d 100644 --- a/homeassistant/components/profiler/services.yaml +++ b/homeassistant/components/profiler/services.yaml @@ -1,10 +1,6 @@ start: - name: Start - description: Start the Profiler fields: seconds: - name: Seconds - description: The number of seconds to run the profiler. default: 60.0 selector: number: @@ -12,12 +8,8 @@ start: max: 3600 unit_of_measurement: seconds memory: - name: Memory - description: Start the Memory Profiler fields: seconds: - name: Seconds - description: The number of seconds to run the memory profiler. default: 60.0 selector: number: @@ -25,12 +17,8 @@ memory: max: 3600 unit_of_measurement: seconds start_log_objects: - name: Start logging objects - description: Start logging growth of objects in memory fields: scan_interval: - name: Scan interval - description: The number of seconds between logging objects. default: 30.0 selector: number: @@ -38,26 +26,16 @@ start_log_objects: max: 3600 unit_of_measurement: seconds stop_log_objects: - name: Stop logging objects - description: Stop logging growth of objects in memory. dump_log_objects: - name: Dump log objects - description: Dump the repr of all matching objects to the log. fields: type: - name: Type - description: The type of objects to dump to the log. required: true example: State selector: text: start_log_object_sources: - name: Start logging object sources - description: Start logging sources of new objects in memory fields: scan_interval: - name: Scan interval - description: The number of seconds between logging objects. default: 30.0 selector: number: @@ -65,8 +43,6 @@ start_log_object_sources: max: 3600 unit_of_measurement: seconds max_objects: - name: Maximum objects - description: The maximum number of objects to log. default: 5 selector: number: @@ -74,14 +50,6 @@ start_log_object_sources: max: 30 unit_of_measurement: objects stop_log_object_sources: - name: Stop logging object sources - description: Stop logging sources of new objects in memory. lru_stats: - name: Log LRU stats - description: Log the stats of all lru caches. log_thread_frames: - name: Log thread frames - description: Log the current frames for all threads. log_event_loop_scheduled: - name: Log event loop scheduled - description: Log what is scheduled in the event loop. diff --git a/homeassistant/components/profiler/strings.json b/homeassistant/components/profiler/strings.json index 394c46563cd442..ee6f215e59bced 100644 --- a/homeassistant/components/profiler/strings.json +++ b/homeassistant/components/profiler/strings.json @@ -8,5 +8,81 @@ "abort": { "single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]" } + }, + "services": { + "start": { + "name": "Start", + "description": "Starts the Profiler.", + "fields": { + "seconds": { + "name": "Seconds", + "description": "The number of seconds to run the profiler." + } + } + }, + "memory": { + "name": "Memory", + "description": "Starts the Memory Profiler.", + "fields": { + "seconds": { + "name": "Seconds", + "description": "The number of seconds to run the memory profiler." + } + } + }, + "start_log_objects": { + "name": "Start logging objects", + "description": "Starts logging growth of objects in memory.", + "fields": { + "scan_interval": { + "name": "Scan interval", + "description": "The number of seconds between logging objects." + } + } + }, + "stop_log_objects": { + "name": "Stop logging objects", + "description": "Stops logging growth of objects in memory." + }, + "dump_log_objects": { + "name": "Dump log objects", + "description": "Dumps the repr of all matching objects to the log.", + "fields": { + "type": { + "name": "Type", + "description": "The type of objects to dump to the log." + } + } + }, + "start_log_object_sources": { + "name": "Start logging object sources", + "description": "Starts logging sources of new objects in memory.", + "fields": { + "scan_interval": { + "name": "Scan interval", + "description": "The number of seconds between logging objects." + }, + "max_objects": { + "name": "Maximum objects", + "description": "The maximum number of objects to log." + } + } + }, + "stop_log_object_sources": { + "name": "Stop logging object sources", + "description": "Stops logging sources of new objects in memory." + }, + "lru_stats": { + "name": "Log LRU stats", + "description": "Logs the stats of all lru caches." + }, + "log_thread_frames": { + "name": "Log thread frames", + "description": "Logs the current frames for all threads." + }, + "log_event_loop_scheduled": { + "name": "Log event loop scheduled", + "description": "Logs what is scheduled in the event loop." + } } } diff --git a/homeassistant/components/prosegur/services.yaml b/homeassistant/components/prosegur/services.yaml index 0db63cb7adf886..e02eb2e60e5d14 100644 --- a/homeassistant/components/prosegur/services.yaml +++ b/homeassistant/components/prosegur/services.yaml @@ -1,6 +1,4 @@ request_image: - name: Request Camera image - description: Request a new image from a Prosegur Camera target: entity: domain: camera diff --git a/homeassistant/components/prosegur/strings.json b/homeassistant/components/prosegur/strings.json index a6c7fcc4a76f1d..9b9ac45fc85c29 100644 --- a/homeassistant/components/prosegur/strings.json +++ b/homeassistant/components/prosegur/strings.json @@ -30,5 +30,11 @@ "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" } + }, + "services": { + "request_image": { + "name": "Request camera image", + "description": "Requests a new image from a Prosegur camera." + } } } diff --git a/homeassistant/components/ps4/services.yaml b/homeassistant/components/ps4/services.yaml index f1f20506edb3f6..0a93f87a2495e9 100644 --- a/homeassistant/components/ps4/services.yaml +++ b/homeassistant/components/ps4/services.yaml @@ -1,18 +1,12 @@ send_command: - name: Send command - description: Emulate button press for PlayStation 4. fields: entity_id: - name: Entity - description: Name of entity to send command. required: true selector: entity: integration: ps4 domain: media_player command: - name: Command - description: Button to press. required: true selector: select: diff --git a/homeassistant/components/ps4/strings.json b/homeassistant/components/ps4/strings.json index 9518af77dbcfd9..644b2d61216100 100644 --- a/homeassistant/components/ps4/strings.json +++ b/homeassistant/components/ps4/strings.json @@ -38,5 +38,21 @@ "port_987_bind_error": "Could not bind to port 987. Refer to the [documentation](https://www.home-assistant.io/components/ps4/) for additional info.", "port_997_bind_error": "Could not bind to port 997. Refer to the [documentation](https://www.home-assistant.io/components/ps4/) for additional info." } + }, + "services": { + "send_command": { + "name": "Send command", + "description": "Emulates button press for PlayStation 4.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name of entity to send command." + }, + "command": { + "name": "Command", + "description": "Button to press." + } + } + } } } diff --git a/homeassistant/components/python_script/services.yaml b/homeassistant/components/python_script/services.yaml index e9f860f1a6289f..613c6cbc9e21f7 100644 --- a/homeassistant/components/python_script/services.yaml +++ b/homeassistant/components/python_script/services.yaml @@ -1,5 +1,3 @@ # Describes the format for available python_script services reload: - name: Reload - description: Reload all available python_scripts diff --git a/homeassistant/components/python_script/strings.json b/homeassistant/components/python_script/strings.json new file mode 100644 index 00000000000000..9898a8ad8665eb --- /dev/null +++ b/homeassistant/components/python_script/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "reload": { + "name": "Reload", + "description": "Reloads all available Python scripts." + } + } +} From ea28bd3c9c144b70375f747f918aceca35b48f69 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 00:34:45 +0200 Subject: [PATCH 065/154] Update pre-commit to 3.3.3 (#96359) --- requirements_test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_test.txt b/requirements_test.txt index 11920917a5913f..2834ea5967271e 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -12,7 +12,7 @@ coverage==7.2.4 freezegun==1.2.2 mock-open==1.4.0 mypy==1.4.1 -pre-commit==3.1.0 +pre-commit==3.3.3 pydantic==1.10.11 pylint==2.17.4 pylint-per-file-ignores==1.2.1 From c6b36b6db44e175f1aa2fc71c6c6acd09f21f411 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 01:08:31 +0200 Subject: [PATCH 066/154] Update RestrictedPython to 6.1 (#96358) --- homeassistant/components/python_script/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/python_script/manifest.json b/homeassistant/components/python_script/manifest.json index 63aa2f2f9162bb..ea153be11cf1f9 100644 --- a/homeassistant/components/python_script/manifest.json +++ b/homeassistant/components/python_script/manifest.json @@ -5,5 +5,5 @@ "documentation": "https://www.home-assistant.io/integrations/python_script", "loggers": ["RestrictedPython"], "quality_scale": "internal", - "requirements": ["RestrictedPython==6.0"] + "requirements": ["RestrictedPython==6.1"] } diff --git a/requirements_all.txt b/requirements_all.txt index 27884a263f06ca..0cb289d748fb75 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -121,7 +121,7 @@ PyXiaomiGateway==0.14.3 RachioPy==1.0.3 # homeassistant.components.python_script -RestrictedPython==6.0 +RestrictedPython==6.1 # homeassistant.components.remember_the_milk RtmAPI==0.7.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 5210e0e335b340..04065df19c1307 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -108,7 +108,7 @@ PyXiaomiGateway==0.14.3 RachioPy==1.0.3 # homeassistant.components.python_script -RestrictedPython==6.0 +RestrictedPython==6.1 # homeassistant.components.remember_the_milk RtmAPI==0.7.2 From 62fe4957c96447a1c0b86a530ae846fca2837d97 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 01:18:22 +0200 Subject: [PATCH 067/154] Migrate integration services (Q-S) to support translations (#96378) --- .../components/qvr_pro/services.yaml | 8 - homeassistant/components/qvr_pro/strings.json | 24 +++ homeassistant/components/rachio/services.yaml | 22 --- homeassistant/components/rachio/strings.json | 56 ++++++ .../components/rainbird/services.yaml | 10 -- .../components/rainbird/strings.json | 26 +++ .../components/rainmachine/services.yaml | 86 --------- .../components/rainmachine/strings.json | 166 ++++++++++++++++++ .../remember_the_milk/services.yaml | 13 -- .../components/remember_the_milk/strings.json | 28 +++ .../components/renault/services.yaml | 15 -- homeassistant/components/renault/strings.json | 44 +++++ homeassistant/components/rest/services.yaml | 2 - homeassistant/components/rest/strings.json | 8 + homeassistant/components/rflink/services.yaml | 6 - homeassistant/components/rflink/strings.json | 18 ++ homeassistant/components/rfxtrx/services.yaml | 4 - homeassistant/components/rfxtrx/strings.json | 12 ++ homeassistant/components/ring/services.yaml | 2 - homeassistant/components/ring/strings.json | 6 + homeassistant/components/roku/services.yaml | 4 - homeassistant/components/roku/strings.json | 12 ++ homeassistant/components/roon/services.yaml | 4 - homeassistant/components/roon/strings.json | 12 ++ .../components/route53/services.yaml | 2 - homeassistant/components/route53/strings.json | 8 + .../components/sabnzbd/services.yaml | 14 -- homeassistant/components/sabnzbd/strings.json | 36 ++++ .../components/screenlogic/services.yaml | 4 - .../components/screenlogic/strings.json | 12 ++ .../components/sensibo/services.yaml | 46 ----- homeassistant/components/sensibo/strings.json | 104 +++++++++++ .../components/shopping_list/services.yaml | 28 --- .../components/shopping_list/strings.json | 64 +++++++ .../components/simplisafe/services.yaml | 36 ---- .../components/simplisafe/strings.json | 80 +++++++++ .../components/smarttub/services.yaml | 16 -- .../components/smarttub/strings.json | 46 +++++ homeassistant/components/smtp/services.yaml | 2 - homeassistant/components/smtp/strings.json | 8 + .../components/snapcast/services.yaml | 16 -- .../components/snapcast/strings.json | 38 ++++ homeassistant/components/snips/services.yaml | 28 --- homeassistant/components/snips/strings.json | 68 +++++++ homeassistant/components/snooz/services.yaml | 10 -- homeassistant/components/snooz/strings.json | 26 +++ .../components/songpal/services.yaml | 6 - homeassistant/components/songpal/strings.json | 16 ++ homeassistant/components/sonos/services.yaml | 38 ---- homeassistant/components/sonos/strings.json | 90 ++++++++++ .../components/soundtouch/services.yaml | 22 --- .../components/soundtouch/strings.json | 54 ++++++ .../components/squeezebox/services.yaml | 22 --- .../components/squeezebox/strings.json | 44 +++++ .../components/starline/services.yaml | 13 -- .../components/starline/strings.json | 26 +++ .../components/streamlabswater/services.yaml | 4 - .../components/streamlabswater/strings.json | 14 ++ homeassistant/components/subaru/services.yaml | 4 - homeassistant/components/subaru/strings.json | 13 +- .../components/surepetcare/services.yaml | 10 -- .../components/surepetcare/strings.json | 30 ++++ .../components/switcher_kis/services.yaml | 8 - .../components/switcher_kis/strings.json | 22 +++ .../components/synology_dsm/services.yaml | 8 - .../components/synology_dsm/strings.json | 142 +++++++++++---- .../components/system_bridge/services.yaml | 24 --- .../components/system_bridge/strings.json | 58 ++++++ 68 files changed, 1380 insertions(+), 568 deletions(-) create mode 100644 homeassistant/components/qvr_pro/strings.json create mode 100644 homeassistant/components/remember_the_milk/strings.json create mode 100644 homeassistant/components/rest/strings.json create mode 100644 homeassistant/components/rflink/strings.json create mode 100644 homeassistant/components/route53/strings.json create mode 100644 homeassistant/components/smtp/strings.json create mode 100644 homeassistant/components/snips/strings.json create mode 100644 homeassistant/components/streamlabswater/strings.json diff --git a/homeassistant/components/qvr_pro/services.yaml b/homeassistant/components/qvr_pro/services.yaml index edb879c784a2bb..0dad311f899550 100644 --- a/homeassistant/components/qvr_pro/services.yaml +++ b/homeassistant/components/qvr_pro/services.yaml @@ -1,22 +1,14 @@ start_record: - name: Start record - description: Start QVR Pro recording on specified channel. fields: guid: - name: GUID - description: GUID of the channel to start recording. required: true example: "245EBE933C0A597EBE865C0A245E0002" selector: text: stop_record: - name: Stop record - description: Stop QVR Pro recording on specified channel. fields: guid: - name: GUID - description: GUID of the channel to stop recording. required: true example: "245EBE933C0A597EBE865C0A245E0002" selector: diff --git a/homeassistant/components/qvr_pro/strings.json b/homeassistant/components/qvr_pro/strings.json new file mode 100644 index 00000000000000..6f37bcce85e185 --- /dev/null +++ b/homeassistant/components/qvr_pro/strings.json @@ -0,0 +1,24 @@ +{ + "services": { + "start_record": { + "name": "Start record", + "description": "Starts QVR Pro recording on specified channel.", + "fields": { + "guid": { + "name": "GUID", + "description": "GUID of the channel to start recording." + } + } + }, + "stop_record": { + "name": "Stop record", + "description": "Stops QVR Pro recording on specified channel.", + "fields": { + "guid": { + "name": "GUID", + "description": "GUID of the channel to stop recording." + } + } + } + } +} diff --git a/homeassistant/components/rachio/services.yaml b/homeassistant/components/rachio/services.yaml index 67463a2217221a..6a6a8bf5cf68cb 100644 --- a/homeassistant/components/rachio/services.yaml +++ b/homeassistant/components/rachio/services.yaml @@ -1,14 +1,10 @@ set_zone_moisture_percent: - name: Set zone moisture percent - description: Set the moisture percentage of a zone or list of zones. target: entity: integration: rachio domain: switch fields: percent: - name: Percent - description: Set the desired zone moisture percentage. required: true selector: number: @@ -16,33 +12,23 @@ set_zone_moisture_percent: max: 100 unit_of_measurement: "%" start_multiple_zone_schedule: - name: Start multiple zones - description: Create a custom schedule of zones and runtimes. Note that all zones should be on the same controller to avoid issues. target: entity: integration: rachio domain: switch fields: duration: - name: Duration - description: Number of minutes to run the zone(s). If only 1 duration is given, that time will be used for all zones. If given a list of durations, the durations will apply to the respective zones listed above. example: 15, 20 required: true selector: object: pause_watering: - name: Pause watering - description: Pause any currently running zones or schedules. fields: devices: - name: Devices - description: Name of controllers to pause. Defaults to all controllers on the account if not provided. example: "Main House" selector: text: duration: - name: Duration - description: The time to pause running schedules. default: 60 selector: number: @@ -50,22 +36,14 @@ pause_watering: max: 60 unit_of_measurement: "minutes" resume_watering: - name: Resume watering - description: Resume any paused zone runs or schedules. fields: devices: - name: Devices - description: Name of controllers to resume. Defaults to all controllers on the account if not provided. example: "Main House" selector: text: stop_watering: - name: Stop watering - description: Stop any currently running zones or schedules. fields: devices: - name: Devices - description: Name of controllers to stop. Defaults to all controllers on the account if not provided. example: "Main House" selector: text: diff --git a/homeassistant/components/rachio/strings.json b/homeassistant/components/rachio/strings.json index 697b0bce2db2a4..3d776193432e80 100644 --- a/homeassistant/components/rachio/strings.json +++ b/homeassistant/components/rachio/strings.json @@ -26,5 +26,61 @@ } } } + }, + "services": { + "set_zone_moisture_percent": { + "name": "Set zone moisture percent", + "description": "Sets the moisture percentage of a zone or list of zones.", + "fields": { + "percent": { + "name": "Percent", + "description": "Set the desired zone moisture percentage." + } + } + }, + "start_multiple_zone_schedule": { + "name": "Start multiple zones", + "description": "Creates a custom schedule of zones and runtimes. Note that all zones should be on the same controller to avoid issues.", + "fields": { + "duration": { + "name": "Duration", + "description": "Number of minutes to run the zone(s). If only 1 duration is given, that time will be used for all zones. If given a list of durations, the durations will apply to the respective zones listed above." + } + } + }, + "pause_watering": { + "name": "Pause watering", + "description": "Pause any currently running zones or schedules.", + "fields": { + "devices": { + "name": "Devices", + "description": "Name of controllers to pause. Defaults to all controllers on the account if not provided." + }, + "duration": { + "name": "Duration", + "description": "The time to pause running schedules." + } + } + }, + "resume_watering": { + "name": "Resume watering", + "description": "Resume any paused zone runs or schedules.", + "fields": { + "devices": { + "name": "Devices", + "description": "Name of controllers to resume. Defaults to all controllers on the account if not provided." + } + } + }, + "stop_watering": { + "name": "Stop watering", + "description": "Stop any currently running zones or schedules.", + "fields": { + "devices": { + "name": "Devices", + "description": "Name of controllers to stop. Defaults to all controllers on the account if not provided." + } + } + } } } diff --git a/homeassistant/components/rainbird/services.yaml b/homeassistant/components/rainbird/services.yaml index 34f89ec279bdd5..11226966b0af01 100644 --- a/homeassistant/components/rainbird/services.yaml +++ b/homeassistant/components/rainbird/services.yaml @@ -1,14 +1,10 @@ start_irrigation: - name: Start irrigation - description: Start the irrigation target: entity: integration: rainbird domain: switch fields: duration: - name: Duration - description: Duration for this sprinkler to be turned on required: true selector: number: @@ -16,19 +12,13 @@ start_irrigation: max: 1440 unit_of_measurement: "minutes" set_rain_delay: - name: Set rain delay - description: Set how long automatic irrigation is turned off. fields: config_entry_id: - name: Rainbird Controller Configuration Entry - description: The setting will be adjusted on the specified controller required: true selector: config_entry: integration: rainbird duration: - name: Duration - description: Duration for this system to be turned off. required: true selector: number: diff --git a/homeassistant/components/rainbird/strings.json b/homeassistant/components/rainbird/strings.json index a98baead976ae6..9f4d0c2e34dc16 100644 --- a/homeassistant/components/rainbird/strings.json +++ b/homeassistant/components/rainbird/strings.json @@ -44,5 +44,31 @@ "name": "Raindelay" } } + }, + "services": { + "start_irrigation": { + "name": "Start irrigation", + "description": "Starts the irrigation.", + "fields": { + "duration": { + "name": "Duration", + "description": "Duration for this sprinkler to be turned on." + } + } + }, + "set_rain_delay": { + "name": "Set rain delay", + "description": "Sets how long automatic irrigation is turned off.", + "fields": { + "config_entry_id": { + "name": "Rainbird Controller Configuration Entry", + "description": "The setting will be adjusted on the specified controller." + }, + "duration": { + "name": "Duration", + "description": "Duration for this system to be turned off." + } + } + } } } diff --git a/homeassistant/components/rainmachine/services.yaml b/homeassistant/components/rainmachine/services.yaml index 9aa2bb7f50a475..2f799afd028d18 100644 --- a/homeassistant/components/rainmachine/services.yaml +++ b/homeassistant/components/rainmachine/services.yaml @@ -1,18 +1,12 @@ # Describes the format for available RainMachine services pause_watering: - name: Pause All Watering - description: Pause all watering activities for a number of seconds fields: device_id: - name: Controller - description: The controller whose watering activities should be paused required: true selector: device: integration: rainmachine seconds: - name: Duration - description: The amount of time (in seconds) to pause watering required: true selector: number: @@ -20,41 +14,29 @@ pause_watering: max: 43200 unit_of_measurement: seconds restrict_watering: - name: Restrict All Watering - description: Restrict all watering activities from starting for a time period fields: device_id: - name: Controller - description: The controller whose watering activities should be restricted required: true selector: device: integration: rainmachine duration: - name: Duration - description: The time period to restrict watering activities from starting required: true default: "01:00:00" selector: text: start_program: - name: Start Program - description: Start a program target: entity: integration: rainmachine domain: switch start_zone: - name: Start Zone - description: Start a zone target: entity: integration: rainmachine domain: switch fields: zone_run_time: - name: Run Time - description: The amount of time (in seconds) to run the zone default: 600 selector: number: @@ -62,55 +44,37 @@ start_zone: max: 86400 mode: box stop_all: - name: Stop All Watering - description: Stop all watering activities fields: device_id: - name: Controller - description: The controller whose watering activities should be stopped required: true selector: device: integration: rainmachine stop_program: - name: Stop Program - description: Stop a program target: entity: integration: rainmachine domain: switch stop_zone: - name: Stop Zone - description: Stop a zone target: entity: integration: rainmachine domain: switch unpause_watering: - name: Unpause All Watering - description: Unpause all paused watering activities fields: device_id: - name: Controller - description: The controller whose watering activities should be unpaused required: true selector: device: integration: rainmachine push_flow_meter_data: - name: Push Flow Meter Data - description: Push Flow Meter data to the RainMachine device. fields: device_id: - name: Controller - description: The controller to send flow meter data to required: true selector: device: integration: rainmachine value: - name: Value - description: The flow meter value to send required: true selector: number: @@ -119,8 +83,6 @@ push_flow_meter_data: step: 0.1 mode: box unit_of_measurement: - name: Unit of Measurement - description: The flow meter units to send selector: select: options: @@ -129,30 +91,16 @@ push_flow_meter_data: - "litre" - "m3" push_weather_data: - name: Push Weather Data - description: >- - Push Weather Data from Home Assistant to the RainMachine device. - - Local Weather Push service should be enabled from Settings > Weather > Developer tab for RainMachine to consider the values being sent. - Units must be sent in metric; no conversions are performed by the integraion. - - See details of RainMachine API Here: https://rainmachine.docs.apiary.io/#reference/weather-services/parserdata/post fields: device_id: - name: Controller - description: The controller for the weather data to be pushed. required: true selector: device: integration: rainmachine timestamp: - name: Timestamp - description: UNIX Timestamp for the Weather Data. If omitted, the RainMachine device's local time at the time of the call is used. selector: text: mintemp: - name: Min Temp - description: Minimum Temperature (°C). selector: number: min: -40 @@ -160,8 +108,6 @@ push_weather_data: step: 0.1 unit_of_measurement: "°C" maxtemp: - name: Max Temp - description: Maximum Temperature (°C). selector: number: min: -40 @@ -169,8 +115,6 @@ push_weather_data: step: 0.1 unit_of_measurement: "°C" temperature: - name: Temperature - description: Current Temperature (°C). selector: number: min: -40 @@ -178,16 +122,12 @@ push_weather_data: step: 0.1 unit_of_measurement: "°C" wind: - name: Wind Speed - description: Wind Speed (m/s) selector: number: min: 0 max: 65 unit_of_measurement: "m/s" solarrad: - name: Solar Radiation - description: Solar Radiation (MJ/m²/h) selector: number: min: 0 @@ -195,67 +135,45 @@ push_weather_data: step: 0.1 unit_of_measurement: "MJ/m²/h" et: - name: Evapotranspiration - description: Evapotranspiration (mm) selector: number: min: 0 max: 1000 unit_of_measurement: "mm" qpf: - name: Quantitative Precipitation Forecast - description: >- - Quantitative Precipitation Forecast (mm), or QPF. Note: QPF values shouldn't - be send as cumulative values but the measured/forecasted values for each hour or day. - The RainMachine Mixer will sum all QPF values in the current day to have the day total QPF. selector: number: min: 0 max: 1000 unit_of_measurement: "mm" rain: - name: Measured Rainfall - description: >- - Measured Rainfail (mm). Note: RAIN values shouldn't be send as cumulative values but the - measured/forecasted values for each hour or day. The RainMachine Mixer will sum all RAIN values - in the current day to have the day total RAIN. selector: number: min: 0 max: 1000 unit_of_measurement: "mm" minrh: - name: Min Relative Humidity - description: Min Relative Humidity (%RH) selector: number: min: 0 max: 100 unit_of_measurement: "%" maxrh: - name: Max Relative Humidity - description: Max Relative Humidity (%RH) selector: number: min: 0 max: 100 unit_of_measurement: "%" condition: - name: Weather Condition Code - description: Current weather condition code (WNUM). selector: text: pressure: - name: Barametric Pressure - description: Barametric Pressure (kPa) selector: number: min: 60 max: 110 unit_of_measurement: "kPa" dewpoint: - name: Dew Point - description: Dew Point (°C). selector: number: min: -40 @@ -263,12 +181,8 @@ push_weather_data: step: 0.1 unit_of_measurement: "°C" unrestrict_watering: - name: Unrestrict All Watering - description: Unrestrict all watering activities fields: device_id: - name: Controller - description: The controller whose watering activities should be unrestricted required: true selector: device: diff --git a/homeassistant/components/rainmachine/strings.json b/homeassistant/components/rainmachine/strings.json index 884d05359a61bb..783c876fe627fe 100644 --- a/homeassistant/components/rainmachine/strings.json +++ b/homeassistant/components/rainmachine/strings.json @@ -97,5 +97,171 @@ "name": "Firmware" } } + }, + "services": { + "pause_watering": { + "name": "Pause all watering", + "description": "Pauses all watering activities for a number of seconds.", + "fields": { + "device_id": { + "name": "Controller", + "description": "The controller whose watering activities should be paused." + }, + "seconds": { + "name": "Duration", + "description": "The amount of time (in seconds) to pause watering." + } + } + }, + "restrict_watering": { + "name": "Restrict all watering", + "description": "Restricts all watering activities from starting for a time period.", + "fields": { + "device_id": { + "name": "Controller", + "description": "The controller whose watering activities should be restricted." + }, + "duration": { + "name": "Duration", + "description": "The time period to restrict watering activities from starting." + } + } + }, + "start_program": { + "name": "Start program", + "description": "Starts a program." + }, + "start_zone": { + "name": "Start zone", + "description": "Starts a zone.", + "fields": { + "zone_run_time": { + "name": "Run time", + "description": "The amount of time (in seconds) to run the zone." + } + } + }, + "stop_all": { + "name": "Stop all watering", + "description": "Stops all watering activities.", + "fields": { + "device_id": { + "name": "Controller", + "description": "The controller whose watering activities should be stopped." + } + } + }, + "stop_program": { + "name": "Stop program", + "description": "Stops a program." + }, + "stop_zone": { + "name": "Stop zone", + "description": "Stops a zone." + }, + "unpause_watering": { + "name": "Unpause all watering", + "description": "Unpauses all paused watering activities.", + "fields": { + "device_id": { + "name": "Controller", + "description": "The controller whose watering activities should be unpaused." + } + } + }, + "push_flow_meter_data": { + "name": "Push flow meter data", + "description": "Push flow meter data to the RainMachine device.", + "fields": { + "device_id": { + "name": "Controller", + "description": "The controller to send flow meter data to." + }, + "value": { + "name": "Value", + "description": "The flow meter value to send." + }, + "unit_of_measurement": { + "name": "Unit of measurement", + "description": "The flow meter units to send." + } + } + }, + "push_weather_data": { + "name": "Push weather data", + "description": "Push weather data from Home Assistant to the RainMachine device.\nLocal Weather Push service should be enabled from Settings > Weather > Developer tab for RainMachine to consider the values being sent. Units must be sent in metric; no conversions are performed by the integraion.\nSee details of RainMachine API Here: https://rainmachine.docs.apiary.io/#reference/weather-services/parserdata/post.", + "fields": { + "device_id": { + "name": "Controller", + "description": "The controller for the weather data to be pushed." + }, + "timestamp": { + "name": "Timestamp", + "description": "UNIX Timestamp for the weather data. If omitted, the RainMachine device's local time at the time of the call is used." + }, + "mintemp": { + "name": "Min temp", + "description": "Minimum temperature (\u00b0C)." + }, + "maxtemp": { + "name": "Max temp", + "description": "Maximum temperature (\u00b0C)." + }, + "temperature": { + "name": "Temperature", + "description": "Current temperature (\u00b0C)." + }, + "wind": { + "name": "Wind speed", + "description": "Wind speed (m/s)." + }, + "solarrad": { + "name": "Solar radiation", + "description": "Solar radiation (MJ/m\u00b2/h)." + }, + "et": { + "name": "Evapotranspiration", + "description": "Evapotranspiration (mm)." + }, + "qpf": { + "name": "Quantitative Precipitation Forecast", + "description": "Quantitative Precipitation Forecast (mm), or QPF. Note: QPF values shouldn't be send as cumulative values but the measured/forecasted values for each hour or day. The RainMachine Mixer will sum all QPF values in the current day to have the day total QPF." + }, + "rain": { + "name": "Measured rainfall", + "description": "Measured rainfail (mm). Note: RAIN values shouldn't be send as cumulative values but the measured/forecasted values for each hour or day. The RainMachine Mixer will sum all RAIN values in the current day to have the day total RAIN." + }, + "minrh": { + "name": "Min relative humidity", + "description": "Min relative humidity (%RH)." + }, + "maxrh": { + "name": "Max relative humidity", + "description": "Max relative humidity (%RH)." + }, + "condition": { + "name": "Weather condition code", + "description": "Current weather condition code (WNUM)." + }, + "pressure": { + "name": "Barametric pressure", + "description": "Barametric pressure (kPa)." + }, + "dewpoint": { + "name": "Dew point", + "description": "Dew point (\u00b0C)." + } + } + }, + "unrestrict_watering": { + "name": "Unrestrict all watering", + "description": "Unrestrict all watering activities.", + "fields": { + "device_id": { + "name": "Controller", + "description": "The controller whose watering activities should be unrestricted." + } + } + } } } diff --git a/homeassistant/components/remember_the_milk/services.yaml b/homeassistant/components/remember_the_milk/services.yaml index 1458075fbd5635..5e94b2bf7d479e 100644 --- a/homeassistant/components/remember_the_milk/services.yaml +++ b/homeassistant/components/remember_the_milk/services.yaml @@ -1,33 +1,20 @@ # Describes the format for available Remember The Milk services create_task: - name: Create task - description: >- - Create (or update) a new task in your Remember The Milk account. If you want to update a task - later on, you have to set an "id" when creating the task. - Note: Updating a tasks does not support the smart syntax. fields: name: - name: Name - description: name of the new task, you can use the smart syntax here required: true example: "do this ^today #from_hass" selector: text: id: - name: ID - description: Identifier for the task you're creating, can be used to update or complete the task later on example: myid selector: text: complete_task: - name: Complete task - description: Complete a tasks that was privously created. fields: id: - name: ID - description: identifier that was defined when creating the task required: true example: myid selector: diff --git a/homeassistant/components/remember_the_milk/strings.json b/homeassistant/components/remember_the_milk/strings.json new file mode 100644 index 00000000000000..15ca4c36da87e6 --- /dev/null +++ b/homeassistant/components/remember_the_milk/strings.json @@ -0,0 +1,28 @@ +{ + "services": { + "create_task": { + "name": "Create task", + "description": "Creates (or update) a new task in your Remember The Milk account. If you want to update a task later on, you have to set an \"id\" when creating the task. Note: Updating a tasks does not support the smart syntax.", + "fields": { + "name": { + "name": "Name", + "description": "Name of the new task, you can use the smart syntax here." + }, + "id": { + "name": "ID", + "description": "Identifier for the task you're creating, can be used to update or complete the task later on." + } + } + }, + "complete_task": { + "name": "Complete task", + "description": "Completes a tasks that was privously created.", + "fields": { + "id": { + "name": "ID", + "description": "Identifier that was defined when creating the task." + } + } + } + } +} diff --git a/homeassistant/components/renault/services.yaml b/homeassistant/components/renault/services.yaml index 5911c453c95863..2dc99833d5f93d 100644 --- a/homeassistant/components/renault/services.yaml +++ b/homeassistant/components/renault/services.yaml @@ -1,16 +1,11 @@ ac_start: - name: Start A/C - description: Start A/C on vehicle. fields: vehicle: - name: Vehicle - description: The vehicle to send the command to. required: true selector: device: integration: renault temperature: - description: Target A/C temperature in °C. example: "21" required: true selector: @@ -20,36 +15,26 @@ ac_start: step: 0.5 unit_of_measurement: °C when: - description: Timestamp for the start of the A/C (optional - defaults to now). example: "2020-05-01T17:45:00" selector: text: ac_cancel: - name: Cancel A/C - description: Cancel A/C on vehicle. fields: vehicle: - name: Vehicle - description: The vehicle to send the command to. required: true selector: device: integration: renault charge_set_schedules: - name: Update charge schedule - description: Update charge schedule on vehicle. fields: vehicle: - name: Vehicle - description: The vehicle to send the command to. required: true selector: device: integration: renault schedules: - description: Schedule details. example: >- [ { diff --git a/homeassistant/components/renault/strings.json b/homeassistant/components/renault/strings.json index 7cf016187be0c9..e0b8cb0cdf03ed 100644 --- a/homeassistant/components/renault/strings.json +++ b/homeassistant/components/renault/strings.json @@ -151,5 +151,49 @@ "name": "Remote engine start code" } } + }, + "services": { + "ac_start": { + "name": "Start A/C", + "description": "Starts A/C on vehicle.", + "fields": { + "vehicle": { + "name": "Vehicle", + "description": "The vehicle to send the command to." + }, + "temperature": { + "name": "Temperature", + "description": "Target A/C temperature in \u00b0C." + }, + "when": { + "name": "When", + "description": "Timestamp for the start of the A/C (optional - defaults to now)." + } + } + }, + "ac_cancel": { + "name": "Cancel A/C", + "description": "Canceles A/C on vehicle.", + "fields": { + "vehicle": { + "name": "Vehicle", + "description": "The vehicle to send the command to." + } + } + }, + "charge_set_schedules": { + "name": "Update charge schedule", + "description": "Updates charge schedule on vehicle.", + "fields": { + "vehicle": { + "name": "Vehicle", + "description": "The vehicle to send the command to." + }, + "schedules": { + "name": "Schedules", + "description": "Schedule details." + } + } + } } } diff --git a/homeassistant/components/rest/services.yaml b/homeassistant/components/rest/services.yaml index 9ba509b63f6f47..c983a105c93977 100644 --- a/homeassistant/components/rest/services.yaml +++ b/homeassistant/components/rest/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload all rest entities and notify services diff --git a/homeassistant/components/rest/strings.json b/homeassistant/components/rest/strings.json new file mode 100644 index 00000000000000..afbab8d8040ab5 --- /dev/null +++ b/homeassistant/components/rest/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "reload": { + "name": "Reload", + "description": "Reloads REST entities from the YAML-configuration." + } + } +} diff --git a/homeassistant/components/rflink/services.yaml b/homeassistant/components/rflink/services.yaml index 8e233bc7aac5d9..1b06a142a59f79 100644 --- a/homeassistant/components/rflink/services.yaml +++ b/homeassistant/components/rflink/services.yaml @@ -1,17 +1,11 @@ send_command: - name: Send command - description: Send device command through RFLink. fields: command: - name: Command - description: The command to be sent. required: true example: "on" selector: text: device_id: - name: Device ID - description: RFLink device ID. required: true example: newkaku_0000c6c2_1 selector: diff --git a/homeassistant/components/rflink/strings.json b/homeassistant/components/rflink/strings.json new file mode 100644 index 00000000000000..2c8eb584ca8aac --- /dev/null +++ b/homeassistant/components/rflink/strings.json @@ -0,0 +1,18 @@ +{ + "services": { + "send_command": { + "name": "Send command", + "description": "Sends device command through RFLink.", + "fields": { + "command": { + "name": "Command", + "description": "The command to be sent." + }, + "device_id": { + "name": "Device ID", + "description": "RFLink device ID." + } + } + } + } +} diff --git a/homeassistant/components/rfxtrx/services.yaml b/homeassistant/components/rfxtrx/services.yaml index 43695554ed0e3d..00640a2ff59dda 100644 --- a/homeassistant/components/rfxtrx/services.yaml +++ b/homeassistant/components/rfxtrx/services.yaml @@ -1,10 +1,6 @@ send: - name: Send - description: Sends a raw event on radio. fields: event: - name: Event - description: A hexadecimal string to send. required: true example: "0b11009e00e6116202020070" selector: diff --git a/homeassistant/components/rfxtrx/strings.json b/homeassistant/components/rfxtrx/strings.json index 7e68f960fca6db..6c49fb38d6cae5 100644 --- a/homeassistant/components/rfxtrx/strings.json +++ b/homeassistant/components/rfxtrx/strings.json @@ -136,5 +136,17 @@ "name": "UV index" } } + }, + "services": { + "send": { + "name": "Send", + "description": "Sends a raw event on radio.", + "fields": { + "event": { + "name": "Event", + "description": "A hexadecimal string to send." + } + } + } } } diff --git a/homeassistant/components/ring/services.yaml b/homeassistant/components/ring/services.yaml index c648f02139b0be..91b8669505b380 100644 --- a/homeassistant/components/ring/services.yaml +++ b/homeassistant/components/ring/services.yaml @@ -1,3 +1 @@ update: - name: Update - description: Updates the data we have for all your ring devices diff --git a/homeassistant/components/ring/strings.json b/homeassistant/components/ring/strings.json index 43209a5a6a3c76..b300e335b191f7 100644 --- a/homeassistant/components/ring/strings.json +++ b/homeassistant/components/ring/strings.json @@ -64,5 +64,11 @@ "name": "[%key:component::siren::title%]" } } + }, + "services": { + "update": { + "name": "Update", + "description": "Updates the data we have for all your ring devices." + } } } diff --git a/homeassistant/components/roku/services.yaml b/homeassistant/components/roku/services.yaml index 16fd51ea95be4c..4a28db94fa4d45 100644 --- a/homeassistant/components/roku/services.yaml +++ b/homeassistant/components/roku/services.yaml @@ -1,14 +1,10 @@ search: - name: Search - description: Emulates opening the search screen and entering the search keyword. target: entity: integration: roku domain: media_player fields: keyword: - name: Keyword - description: The keyword to search for. required: true example: "Space Jam" selector: diff --git a/homeassistant/components/roku/strings.json b/homeassistant/components/roku/strings.json index 04c504def034bf..3510a43c604da5 100644 --- a/homeassistant/components/roku/strings.json +++ b/homeassistant/components/roku/strings.json @@ -20,5 +20,17 @@ "already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]", "unknown": "[%key:common::config_flow::error::unknown%]" } + }, + "services": { + "search": { + "name": "Search", + "description": "Emulates opening the search screen and entering the search keyword.", + "fields": { + "keyword": { + "name": "Keyword", + "description": "The keyword to search for." + } + } + } } } diff --git a/homeassistant/components/roon/services.yaml b/homeassistant/components/roon/services.yaml index 9d9d02f0efc457..1de3e14bbc9ed6 100644 --- a/homeassistant/components/roon/services.yaml +++ b/homeassistant/components/roon/services.yaml @@ -1,14 +1,10 @@ transfer: - name: Transfer - description: Transfer playback from one player to another. target: entity: integration: roon domain: media_player fields: transfer_id: - name: Transfer ID - description: id of the destination player. required: true selector: entity: diff --git a/homeassistant/components/roon/strings.json b/homeassistant/components/roon/strings.json index ce5827e2c6c6cd..f67779e9eaaba7 100644 --- a/homeassistant/components/roon/strings.json +++ b/homeassistant/components/roon/strings.json @@ -21,5 +21,17 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" } + }, + "services": { + "transfer": { + "name": "Transfer", + "description": "Transfers playback from one player to another.", + "fields": { + "transfer_id": { + "name": "Transfer ID", + "description": "ID of the destination player." + } + } + } } } diff --git a/homeassistant/components/route53/services.yaml b/homeassistant/components/route53/services.yaml index 4936a499764010..e800a3a3eeebb7 100644 --- a/homeassistant/components/route53/services.yaml +++ b/homeassistant/components/route53/services.yaml @@ -1,3 +1 @@ update_records: - name: Update records - description: Trigger update of records. diff --git a/homeassistant/components/route53/strings.json b/homeassistant/components/route53/strings.json new file mode 100644 index 00000000000000..12b372d0ce2fd0 --- /dev/null +++ b/homeassistant/components/route53/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "update_records": { + "name": "Update records", + "description": "Triggers update of records." + } + } +} diff --git a/homeassistant/components/sabnzbd/services.yaml b/homeassistant/components/sabnzbd/services.yaml index 2221eed169f404..f1eea1c9469a8b 100644 --- a/homeassistant/components/sabnzbd/services.yaml +++ b/homeassistant/components/sabnzbd/services.yaml @@ -1,36 +1,22 @@ pause: - name: Pause - description: Pauses downloads. fields: api_key: - name: Sabnzbd API key - description: The Sabnzbd API key to pause downloads required: true selector: text: resume: - name: Resume - description: Resumes downloads. fields: api_key: - name: Sabnzbd API key - description: The Sabnzbd API key to resume downloads required: true selector: text: set_speed: - name: Set speed - description: Sets the download speed limit. fields: api_key: - name: Sabnzbd API key - description: The Sabnzbd API key to set speed limit required: true selector: text: speed: - name: Speed - description: Speed limit. If specified as a number with no units, will be interpreted as a percent. If units are provided (e.g., 500K) will be interpreted absolutely. example: 100 default: 100 selector: diff --git a/homeassistant/components/sabnzbd/strings.json b/homeassistant/components/sabnzbd/strings.json index 501e0d33faff58..2989ee5d00be27 100644 --- a/homeassistant/components/sabnzbd/strings.json +++ b/homeassistant/components/sabnzbd/strings.json @@ -13,5 +13,41 @@ "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "invalid_api_key": "[%key:common::config_flow::error::invalid_api_key%]" } + }, + "services": { + "pause": { + "name": "Pause", + "description": "Pauses downloads.", + "fields": { + "api_key": { + "name": "SABnzbd API key", + "description": "The SABnzbd API key to pause downloads." + } + } + }, + "resume": { + "name": "Resume", + "description": "Resumes downloads.", + "fields": { + "api_key": { + "name": "SABnzbd API key", + "description": "The SABnzbd API key to resume downloads." + } + } + }, + "set_speed": { + "name": "Set speed", + "description": "Sets the download speed limit.", + "fields": { + "api_key": { + "name": "SABnzbd API key", + "description": "The SABnzbd API key to set speed limit." + }, + "speed": { + "name": "Speed", + "description": "Speed limit. If specified as a number with no units, will be interpreted as a percent. If units are provided (e.g., 500K) will be interpreted absolutely." + } + } + } } } diff --git a/homeassistant/components/screenlogic/services.yaml b/homeassistant/components/screenlogic/services.yaml index 439d020a432f97..8e4a82a1079911 100644 --- a/homeassistant/components/screenlogic/services.yaml +++ b/homeassistant/components/screenlogic/services.yaml @@ -1,14 +1,10 @@ # ScreenLogic Services set_color_mode: - name: Set Color Mode - description: Sets the color mode for all color-capable lights attached to this ScreenLogic gateway. target: device: integration: screenlogic fields: color_mode: - name: Color Mode - description: The ScreenLogic color mode to set required: true selector: select: diff --git a/homeassistant/components/screenlogic/strings.json b/homeassistant/components/screenlogic/strings.json index b0958d31727002..79b633e28b617a 100644 --- a/homeassistant/components/screenlogic/strings.json +++ b/homeassistant/components/screenlogic/strings.json @@ -35,5 +35,17 @@ } } } + }, + "services": { + "set_color_mode": { + "name": "Set Color Mode", + "description": "Sets the color mode for all color-capable lights attached to this ScreenLogic gateway.", + "fields": { + "color_mode": { + "name": "Color Mode", + "description": "The ScreenLogic color mode to set." + } + } + } } } diff --git a/homeassistant/components/sensibo/services.yaml b/homeassistant/components/sensibo/services.yaml index fbd2625961bc92..7f8252af82029d 100644 --- a/homeassistant/components/sensibo/services.yaml +++ b/homeassistant/components/sensibo/services.yaml @@ -1,14 +1,10 @@ assume_state: - name: Assume state - description: Set Sensibo device to external state target: entity: integration: sensibo domain: climate fields: state: - name: State - description: State to set required: true example: "on" selector: @@ -17,16 +13,12 @@ assume_state: - "on" - "off" enable_timer: - name: Enable Timer - description: Enable the timer with custom time target: entity: integration: sensibo domain: climate fields: minutes: - name: Minutes - description: Countdown for timer (for timer state on) required: false example: 30 selector: @@ -35,44 +27,32 @@ enable_timer: step: 1 mode: box enable_pure_boost: - name: Enable Pure Boost - description: Enable and configure Pure Boost settings target: entity: integration: sensibo domain: climate fields: ac_integration: - name: AC Integration - description: Integrate with Air Conditioner required: true example: true selector: boolean: geo_integration: - name: Geo Integration - description: Integrate with Presence required: true example: true selector: boolean: indoor_integration: - name: Indoor Air Quality - description: Integrate with checking indoor air quality required: true example: true selector: boolean: outdoor_integration: - name: Outdoor Air Quality - description: Integrate with checking outdoor air quality required: true example: true selector: boolean: sensitivity: - name: Sensitivity - description: Set the sensitivity for Pure Boost required: true example: "Normal" selector: @@ -81,16 +61,12 @@ enable_pure_boost: - "Normal" - "Sensitive" full_state: - name: Set full state - description: Set full state for Sensibo device target: entity: integration: sensibo domain: climate fields: mode: - name: HVAC mode - description: HVAC mode to set required: true example: "heat" selector: @@ -103,8 +79,6 @@ full_state: - "dry" - "off" target_temperature: - name: Target Temperature - description: Optionally set target temperature required: false example: 23 selector: @@ -113,32 +87,24 @@ full_state: step: 1 mode: box fan_mode: - name: Fan mode - description: Optionally set fan mode required: false example: "low" selector: text: type: text swing_mode: - name: swing mode - description: Optionally set swing mode required: false example: "fixedBottom" selector: text: type: text horizontal_swing_mode: - name: Horizontal swing mode - description: Optionally set horizontal swing mode required: false example: "fixedLeft" selector: text: type: text light: - name: Light - description: Set light on or off required: false example: "on" selector: @@ -148,16 +114,12 @@ full_state: - "off" - "dim" enable_climate_react: - name: Enable Climate React - description: Enable and configure Climate React target: entity: integration: sensibo domain: climate fields: high_temperature_threshold: - name: Threshold high - description: When temp/humidity goes above required: true example: 24 selector: @@ -167,14 +129,10 @@ enable_climate_react: step: 0.1 mode: box high_temperature_state: - name: State high threshold - description: What should happen at high threshold. Requires full state required: true selector: object: low_temperature_threshold: - name: Threshold low - description: When temp/humidity goes below required: true example: 19 selector: @@ -184,14 +142,10 @@ enable_climate_react: step: 0.1 mode: box low_temperature_state: - name: State low threshold - description: What should happen at low threshold. Requires full state required: true selector: object: smart_type: - name: Trigger type - description: Choose between temperature/feels like/humidity required: true example: "temperature" selector: diff --git a/homeassistant/components/sensibo/strings.json b/homeassistant/components/sensibo/strings.json index 2379e2c2b38c83..6946b21761c37a 100644 --- a/homeassistant/components/sensibo/strings.json +++ b/homeassistant/components/sensibo/strings.json @@ -157,5 +157,109 @@ "name": "Update available" } } + }, + "services": { + "assume_state": { + "name": "Assume state", + "description": "Sets Sensibo device to external state.", + "fields": { + "state": { + "name": "State", + "description": "State to set." + } + } + }, + "enable_timer": { + "name": "Enable timer", + "description": "Enables the timer with custom time.", + "fields": { + "minutes": { + "name": "Minutes", + "description": "Countdown for timer (for timer state on)." + } + } + }, + "enable_pure_boost": { + "name": "Enable pure boost", + "description": "Enables and configures Pure Boost settings.", + "fields": { + "ac_integration": { + "name": "AC integration", + "description": "Integrate with Air Conditioner." + }, + "geo_integration": { + "name": "Geo integration", + "description": "Integrate with Presence." + }, + "indoor_integration": { + "name": "Indoor air quality", + "description": "Integrate with checking indoor air quality." + }, + "outdoor_integration": { + "name": "Outdoor air quality", + "description": "Integrate with checking outdoor air quality." + }, + "sensitivity": { + "name": "Sensitivity", + "description": "Set the sensitivity for Pure Boost." + } + } + }, + "full_state": { + "name": "Set full state", + "description": "Sets full state for Sensibo device.", + "fields": { + "mode": { + "name": "HVAC mode", + "description": "HVAC mode to set." + }, + "target_temperature": { + "name": "Target temperature", + "description": "Set target temperature." + }, + "fan_mode": { + "name": "Fan mode", + "description": "set fan mode." + }, + "swing_mode": { + "name": "Swing mode", + "description": "Set swing mode." + }, + "horizontal_swing_mode": { + "name": "Horizontal swing mode", + "description": "Set horizontal swing mode." + }, + "light": { + "name": "Light", + "description": "Set light on or off." + } + } + }, + "enable_climate_react": { + "name": "Enable climate react", + "description": "Enables and configures climate react.", + "fields": { + "high_temperature_threshold": { + "name": "Threshold high", + "description": "When temp/humidity goes above." + }, + "high_temperature_state": { + "name": "State high threshold", + "description": "What should happen at high threshold. Requires full state." + }, + "low_temperature_threshold": { + "name": "Threshold low", + "description": "When temp/humidity goes below." + }, + "low_temperature_state": { + "name": "State low threshold", + "description": "What should happen at low threshold. Requires full state." + }, + "smart_type": { + "name": "Trigger type", + "description": "Choose between temperature/feels like/humidity." + } + } + } } } diff --git a/homeassistant/components/shopping_list/services.yaml b/homeassistant/components/shopping_list/services.yaml index 250912f49cdd59..402a6c24aeb9e9 100644 --- a/homeassistant/components/shopping_list/services.yaml +++ b/homeassistant/components/shopping_list/services.yaml @@ -1,69 +1,41 @@ add_item: - name: Add item - description: Add an item to the shopping list. fields: name: - name: Name - description: The name of the item to add. required: true example: Beer selector: text: remove_item: - name: Remove item - description: Remove the first item with matching name from the shopping list. fields: name: - name: Name - description: The name of the item to remove. required: true example: Beer selector: text: complete_item: - name: Complete item - description: Mark the first item with matching name as completed in the shopping list. fields: name: - name: Name - description: The name of the item to mark as completed (without removing). required: true example: Beer selector: text: incomplete_item: - name: Incomplete item - description: Mark the first item with matching name as incomplete in the shopping list. fields: name: - description: The name of the item to mark as incomplete. example: Beer required: true selector: text: complete_all: - name: Complete all - description: Mark all items as completed in the shopping list (without removing them from the list). - incomplete_all: - name: Incomplete all - description: Mark all items as incomplete in the shopping list. - clear_completed_items: - name: Clear completed items - description: Clear completed items from the shopping list. - sort: - name: Sort all items - description: Sort all items by name in the shopping list. fields: reverse: - name: Sort reverse - description: Whether to sort in reverse (descending) order. default: false selector: boolean: diff --git a/homeassistant/components/shopping_list/strings.json b/homeassistant/components/shopping_list/strings.json index 5b8197177a02be..598a2bddfffff7 100644 --- a/homeassistant/components/shopping_list/strings.json +++ b/homeassistant/components/shopping_list/strings.json @@ -10,5 +10,69 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_service%]" } + }, + "services": { + "add_item": { + "name": "Add item", + "description": "Adds an item to the shopping list.", + "fields": { + "name": { + "name": "Name", + "description": "The name of the item to add." + } + } + }, + "remove_item": { + "name": "Remove item", + "description": "Removes the first item with matching name from the shopping list.", + "fields": { + "name": { + "name": "Name", + "description": "The name of the item to remove." + } + } + }, + "complete_item": { + "name": "Complete item", + "description": "Marks the first item with matching name as completed in the shopping list.", + "fields": { + "name": { + "name": "Name", + "description": "The name of the item to mark as completed (without removing)." + } + } + }, + "incomplete_item": { + "name": "Incomplete item", + "description": "Marks the first item with matching name as incomplete in the shopping list.", + "fields": { + "name": { + "name": "Name", + "description": "The name of the item to mark as incomplete." + } + } + }, + "complete_all": { + "name": "Complete all", + "description": "Marks all items as completed in the shopping list (without removing them from the list)." + }, + "incomplete_all": { + "name": "Incomplete all", + "description": "Marks all items as incomplete in the shopping list." + }, + "clear_completed_items": { + "name": "Clear completed items", + "description": "Clears completed items from the shopping list." + }, + "sort": { + "name": "Sort all items", + "description": "Sorts all items by name in the shopping list.", + "fields": { + "reverse": { + "name": "Sort reverse", + "description": "Whether to sort in reverse (descending) order." + } + } + } } } diff --git a/homeassistant/components/simplisafe/services.yaml b/homeassistant/components/simplisafe/services.yaml index 8aeefcf7846f24..de4d8fbe534674 100644 --- a/homeassistant/components/simplisafe/services.yaml +++ b/homeassistant/components/simplisafe/services.yaml @@ -1,11 +1,7 @@ # Describes the format for available SimpliSafe services remove_pin: - name: Remove PIN - description: Remove a PIN by its label or value. fields: device_id: - name: System - description: The system to remove the PIN from required: true selector: device: @@ -13,19 +9,13 @@ remove_pin: entity: domain: alarm_control_panel label_or_pin: - name: Label/PIN - description: The label/value to remove. required: true example: Test PIN selector: text: set_pin: - name: Set PIN - description: Set/update a PIN fields: device_id: - name: System - description: The system to set the PIN on required: true selector: device: @@ -33,26 +23,18 @@ set_pin: entity: domain: alarm_control_panel label: - name: Label - description: The label of the PIN required: true example: Test PIN selector: text: pin: - name: PIN - description: The value of the PIN required: true example: 1256 selector: text: set_system_properties: - name: Set system properties - description: Set one or more system properties fields: device_id: - name: System - description: The system whose properties should be set required: true selector: device: @@ -60,16 +42,12 @@ set_system_properties: entity: domain: alarm_control_panel alarm_duration: - name: Alarm duration - description: The length of a triggered alarm selector: number: min: 30 max: 480 unit_of_measurement: seconds alarm_volume: - name: Alarm volume - description: The volume level of a triggered alarm selector: select: options: @@ -78,8 +56,6 @@ set_system_properties: - "high" - "off" chime_volume: - name: Chime volume - description: The volume level of the door chime selector: select: options: @@ -88,45 +64,33 @@ set_system_properties: - "high" - "off" entry_delay_away: - name: Entry delay away - description: How long to delay when entering while "away" selector: number: min: 30 max: 255 unit_of_measurement: seconds entry_delay_home: - name: Entry delay home - description: How long to delay when entering while "home" selector: number: min: 0 max: 255 unit_of_measurement: seconds exit_delay_away: - name: Exit delay away - description: How long to delay when exiting while "away" selector: number: min: 45 max: 255 unit_of_measurement: seconds exit_delay_home: - name: Exit delay home - description: How long to delay when exiting while "home" selector: number: min: 0 max: 255 unit_of_measurement: seconds light: - name: Light - description: Whether the armed light should be visible selector: boolean: voice_prompt_volume: - name: Voice prompt volume - description: The volume level of the voice prompt selector: select: options: diff --git a/homeassistant/components/simplisafe/strings.json b/homeassistant/components/simplisafe/strings.json index 4f230442f8567a..4be806ebbbd761 100644 --- a/homeassistant/components/simplisafe/strings.json +++ b/homeassistant/components/simplisafe/strings.json @@ -36,5 +36,85 @@ "name": "Clear notifications" } } + }, + "services": { + "remove_pin": { + "name": "Remove PIN", + "description": "Removes a PIN by its label or value.", + "fields": { + "device_id": { + "name": "System", + "description": "The system to remove the PIN from." + }, + "label_or_pin": { + "name": "Label/PIN", + "description": "The label/value to remove." + } + } + }, + "set_pin": { + "name": "Set PIN", + "description": "Sets/updates a PIN.", + "fields": { + "device_id": { + "name": "System", + "description": "The system to set the PIN on." + }, + "label": { + "name": "Label", + "description": "The label of the PIN." + }, + "pin": { + "name": "PIN", + "description": "The value of the PIN." + } + } + }, + "set_system_properties": { + "name": "Set system properties", + "description": "Sets one or more system properties.", + "fields": { + "device_id": { + "name": "System", + "description": "The system whose properties should be set." + }, + "alarm_duration": { + "name": "Alarm duration", + "description": "The length of a triggered alarm." + }, + "alarm_volume": { + "name": "Alarm volume", + "description": "The volume level of a triggered alarm." + }, + "chime_volume": { + "name": "Chime volume", + "description": "The volume level of the door chime." + }, + "entry_delay_away": { + "name": "Entry delay away", + "description": "How long to delay when entering while \"away\"." + }, + "entry_delay_home": { + "name": "Entry delay home", + "description": "How long to delay when entering while \"home\"." + }, + "exit_delay_away": { + "name": "Exit delay away", + "description": "How long to delay when exiting while \"away\"." + }, + "exit_delay_home": { + "name": "Exit delay home", + "description": "How long to delay when exiting while \"home\"." + }, + "light": { + "name": "Light", + "description": "Whether the armed light should be visible." + }, + "voice_prompt_volume": { + "name": "Voice prompt volume", + "description": "The volume level of the voice prompt." + } + } + } } } diff --git a/homeassistant/components/smarttub/services.yaml b/homeassistant/components/smarttub/services.yaml index d9890dba35a738..65bd4afb8b7132 100644 --- a/homeassistant/components/smarttub/services.yaml +++ b/homeassistant/components/smarttub/services.yaml @@ -1,14 +1,10 @@ set_primary_filtration: - name: Update primary filtration settings - description: Updates the primary filtration settings target: entity: integration: smarttub domain: sensor fields: duration: - name: Duration - description: The desired duration of the primary filtration cycle default: 8 selector: number: @@ -18,7 +14,6 @@ set_primary_filtration: mode: slider example: 8 start_hour: - description: The hour of the day at which to begin the primary filtration cycle default: 0 example: 2 selector: @@ -28,15 +23,12 @@ set_primary_filtration: unit_of_measurement: "hour" set_secondary_filtration: - name: Update secondary filtration settings - description: Updates the secondary filtration settings target: entity: integration: smarttub domain: sensor fields: mode: - description: The secondary filtration mode. selector: select: options: @@ -47,16 +39,12 @@ set_secondary_filtration: example: "frequent" snooze_reminder: - name: Snooze a reminder - description: Delay a reminder, so that it won't trigger again for a period of time. target: entity: integration: smarttub domain: binary_sensor fields: days: - name: Days - description: The number of days to delay the reminder. required: true example: 7 selector: @@ -66,16 +54,12 @@ snooze_reminder: unit_of_measurement: days reset_reminder: - name: Reset a reminder - description: Reset a reminder, and set the next time it will be triggered. target: entity: integration: smarttub domain: binary_sensor fields: days: - name: Days - description: The number of days when the next reminder should trigger. required: true example: 180 selector: diff --git a/homeassistant/components/smarttub/strings.json b/homeassistant/components/smarttub/strings.json index 25528b8a374d6b..c130feaa620b22 100644 --- a/homeassistant/components/smarttub/strings.json +++ b/homeassistant/components/smarttub/strings.json @@ -21,5 +21,51 @@ "already_configured": "[%key:common::config_flow::abort::already_configured_account%]", "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" } + }, + "services": { + "set_primary_filtration": { + "name": "Update primary filtration settings", + "description": "Updates the primary filtration settings.", + "fields": { + "duration": { + "name": "Duration", + "description": "The desired duration of the primary filtration cycle." + }, + "start_hour": { + "name": "Start hour", + "description": "The hour of the day at which to begin the primary filtration cycle." + } + } + }, + "set_secondary_filtration": { + "name": "Update secondary filtration settings", + "description": "Updates the secondary filtration settings.", + "fields": { + "mode": { + "name": "Mode", + "description": "The secondary filtration mode." + } + } + }, + "snooze_reminder": { + "name": "Snooze a reminder", + "description": "Delay a reminder, so that it won't trigger again for a period of time.", + "fields": { + "days": { + "name": "Days", + "description": "The number of days to delay the reminder." + } + } + }, + "reset_reminder": { + "name": "Reset a reminder", + "description": "Reset a reminder, and set the next time it will be triggered.", + "fields": { + "days": { + "name": "Days", + "description": "The number of days when the next reminder should trigger." + } + } + } } } diff --git a/homeassistant/components/smtp/services.yaml b/homeassistant/components/smtp/services.yaml index c4380a4fc62381..c983a105c93977 100644 --- a/homeassistant/components/smtp/services.yaml +++ b/homeassistant/components/smtp/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload smtp notify services. diff --git a/homeassistant/components/smtp/strings.json b/homeassistant/components/smtp/strings.json new file mode 100644 index 00000000000000..3c72a1a50d1a75 --- /dev/null +++ b/homeassistant/components/smtp/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "reload": { + "name": "Reload", + "description": "Reloads smtp notify services." + } + } +} diff --git a/homeassistant/components/snapcast/services.yaml b/homeassistant/components/snapcast/services.yaml index f80b22dba7edec..aa1a26c353754b 100644 --- a/homeassistant/components/snapcast/services.yaml +++ b/homeassistant/components/snapcast/services.yaml @@ -1,18 +1,12 @@ join: - name: Join - description: Group players together. fields: master: - name: Master - description: Entity ID of the player to synchronize to. required: true selector: entity: integration: snapcast domain: media_player entity_id: - name: Entity - description: The players to join to the "master". selector: target: entity: @@ -20,40 +14,30 @@ join: domain: media_player unjoin: - name: Unjoin - description: Unjoin the player from a group. target: entity: integration: snapcast domain: media_player snapshot: - name: Snapshot - description: Take a snapshot of the media player. target: entity: integration: snapcast domain: media_player restore: - name: Restore - description: Restore a snapshot of the media player. target: entity: integration: snapcast domain: media_player set_latency: - name: Set latency - description: Set client set_latency target: entity: integration: snapcast domain: media_player fields: latency: - name: Latency - description: Latency in master required: true selector: number: diff --git a/homeassistant/components/snapcast/strings.json b/homeassistant/components/snapcast/strings.json index 766bca634955d6..242bf62ab04f8a 100644 --- a/homeassistant/components/snapcast/strings.json +++ b/homeassistant/components/snapcast/strings.json @@ -17,5 +17,43 @@ "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "invalid_host": "[%key:common::config_flow::error::invalid_host%]" } + }, + "services": { + "join": { + "name": "Join", + "description": "Groups players together.", + "fields": { + "master": { + "name": "Master", + "description": "Entity ID of the player to synchronize to." + }, + "entity_id": { + "name": "Entity", + "description": "The players to join to the \"master\"." + } + } + }, + "unjoin": { + "name": "Unjoin", + "description": "Unjoins the player from a group." + }, + "snapshot": { + "name": "Snapshot", + "description": "Takes a snapshot of the media player." + }, + "restore": { + "name": "Restore", + "description": "Restores a snapshot of the media player." + }, + "set_latency": { + "name": "Set latency", + "description": "Sets client set_latency.", + "fields": { + "latency": { + "name": "Latency", + "description": "Latency in master." + } + } + } } } diff --git a/homeassistant/components/snips/services.yaml b/homeassistant/components/snips/services.yaml index df3a46281c87a9..522e1b5b348c8c 100644 --- a/homeassistant/components/snips/services.yaml +++ b/homeassistant/components/snips/services.yaml @@ -1,83 +1,55 @@ feedback_off: - name: Feedback off - description: Turns feedback sounds off. fields: site_id: - name: Site ID - description: Site to turn sounds on, defaults to all sites. example: bedroom default: default selector: text: feedback_on: - name: Feedback on - description: Turns feedback sounds on. fields: site_id: - name: Site ID - description: Site to turn sounds on, defaults to all sites. example: bedroom default: default selector: text: say: - name: Say - description: Send a TTS message to Snips. fields: custom_data: - name: Custom data - description: custom data that will be included with all messages in this session example: user=UserName default: "" selector: text: site_id: - name: Site ID - description: Site to use to start session, defaults to default. example: bedroom default: default selector: text: text: - name: Text - description: Text to say. required: true example: My name is snips selector: text: say_action: - name: Say action - description: Send a TTS message to Snips to listen for a response. fields: can_be_enqueued: - name: Can be enqueued - description: If True, session waits for an open session to end, if False session is dropped if one is running default: true selector: boolean: custom_data: - name: Custom data - description: custom data that will be included with all messages in this session example: user=UserName default: "" selector: text: intent_filter: - name: Intent filter - description: Optional Array of Strings - A list of intents names to restrict the NLU resolution to on the first query. example: "turnOnLights, turnOffLights" selector: object: site_id: - name: Site ID - description: Site to use to start session, defaults to default. example: bedroom default: default selector: text: text: - name: Text - description: Text to say required: true example: My name is snips selector: diff --git a/homeassistant/components/snips/strings.json b/homeassistant/components/snips/strings.json new file mode 100644 index 00000000000000..d6c9f4d53f65b7 --- /dev/null +++ b/homeassistant/components/snips/strings.json @@ -0,0 +1,68 @@ +{ + "services": { + "feedback_off": { + "name": "Feedback off", + "description": "Turns feedback sounds off.", + "fields": { + "site_id": { + "name": "Site ID", + "description": "Site to turn sounds on, defaults to all sites." + } + } + }, + "feedback_on": { + "name": "Feedback on", + "description": "Turns feedback sounds on.", + "fields": { + "site_id": { + "name": "Site ID", + "description": "Site to turn sounds on, defaults to all sites." + } + } + }, + "say": { + "name": "Say", + "description": "Sends a TTS message to Snips.", + "fields": { + "custom_data": { + "name": "Custom data", + "description": "Custom data that will be included with all messages in this session." + }, + "site_id": { + "name": "Site ID", + "description": "Site to use to start session, defaults to default." + }, + "text": { + "name": "Text", + "description": "Text to say." + } + } + }, + "say_action": { + "name": "Say action", + "description": "Sends a TTS message to Snips to listen for a response.", + "fields": { + "can_be_enqueued": { + "name": "Can be enqueued", + "description": "If True, session waits for an open session to end, if False session is dropped if one is running." + }, + "custom_data": { + "name": "Custom data", + "description": "Custom data that will be included with all messages in this session." + }, + "intent_filter": { + "name": "Intent filter", + "description": "Optional Array of Strings - A list of intents names to restrict the NLU resolution to on the first query." + }, + "site_id": { + "name": "Site ID", + "description": "Site to use to start session, defaults to default." + }, + "text": { + "name": "Text", + "description": "Text to say." + } + } + } + } +} diff --git a/homeassistant/components/snooz/services.yaml b/homeassistant/components/snooz/services.yaml index f795edf213ab11..ca9f4883a69d13 100644 --- a/homeassistant/components/snooz/services.yaml +++ b/homeassistant/components/snooz/services.yaml @@ -1,14 +1,10 @@ transition_on: - name: Transition on - description: Transition to a target volume level over time. target: entity: integration: snooz domain: fan fields: duration: - name: Transition duration - description: Time it takes to reach the target volume level. selector: number: min: 1 @@ -16,8 +12,6 @@ transition_on: unit_of_measurement: seconds mode: box volume: - name: Target volume - description: If not specified, the volume level is read from the device. selector: number: min: 1 @@ -25,16 +19,12 @@ transition_on: unit_of_measurement: "%" transition_off: - name: Transition off - description: Transition volume off over time. target: entity: integration: snooz domain: fan fields: duration: - name: Transition duration - description: Time it takes to turn off. selector: number: min: 1 diff --git a/homeassistant/components/snooz/strings.json b/homeassistant/components/snooz/strings.json index 2f957f87072a16..878341f23bc596 100644 --- a/homeassistant/components/snooz/strings.json +++ b/homeassistant/components/snooz/strings.json @@ -23,5 +23,31 @@ "already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]", "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" } + }, + "services": { + "transition_on": { + "name": "Transition on", + "description": "Transitions to a target volume level over time.", + "fields": { + "duration": { + "name": "Transition duration", + "description": "Time it takes to reach the target volume level." + }, + "volume": { + "name": "Target volume", + "description": "If not specified, the volume level is read from the device." + } + } + }, + "transition_off": { + "name": "Transition off", + "description": "Transitions volume off over time.", + "fields": { + "duration": { + "name": "Transition duration", + "description": "Time it takes to turn off." + } + } + } } } diff --git a/homeassistant/components/songpal/services.yaml b/homeassistant/components/songpal/services.yaml index 93485ce47883e2..26da134acddaba 100644 --- a/homeassistant/components/songpal/services.yaml +++ b/homeassistant/components/songpal/services.yaml @@ -1,21 +1,15 @@ set_sound_setting: - name: Set sound setting - description: Change sound setting. target: entity: integration: songpal domain: media_player fields: name: - name: Name - description: Name of the setting. required: true example: "nightMode" selector: text: value: - name: Value - description: Value to set. required: true example: "on" selector: diff --git a/homeassistant/components/songpal/strings.json b/homeassistant/components/songpal/strings.json index 62bff00c78692c..a4df830f1fe8cd 100644 --- a/homeassistant/components/songpal/strings.json +++ b/homeassistant/components/songpal/strings.json @@ -18,5 +18,21 @@ "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", "not_songpal_device": "Not a Songpal device" } + }, + "services": { + "set_sound_setting": { + "name": "Sets sound setting", + "description": "Change sound setting.", + "fields": { + "name": { + "name": "Name", + "description": "Name of the setting." + }, + "value": { + "name": "Value", + "description": "Value to set." + } + } + } } } diff --git a/homeassistant/components/sonos/services.yaml b/homeassistant/components/sonos/services.yaml index 9d61c20f7cb569..f6df83ef6ed287 100644 --- a/homeassistant/components/sonos/services.yaml +++ b/homeassistant/components/sonos/services.yaml @@ -1,49 +1,33 @@ snapshot: - name: Snapshot - description: Take a snapshot of the media player. fields: entity_id: - name: Entity - description: Name of entity that will be snapshot. selector: entity: integration: sonos domain: media_player with_group: - name: With group - description: True or False. Also snapshot the group layout. default: true selector: boolean: restore: - name: Restore - description: Restore a snapshot of the media player. fields: entity_id: - name: Entity - description: Name of entity that will be restored. selector: entity: integration: sonos domain: media_player with_group: - name: With group - description: True or False. Also restore the group layout. default: true selector: boolean: set_sleep_timer: - name: Set timer - description: Set a Sonos timer. target: device: integration: sonos fields: sleep_time: - name: Sleep Time - description: Number of seconds to set the timer. selector: number: min: 0 @@ -51,22 +35,16 @@ set_sleep_timer: unit_of_measurement: seconds clear_sleep_timer: - name: Clear timer - description: Clear a Sonos timer. target: device: integration: sonos play_queue: - name: Play queue - description: Start playing the queue from the first item. target: device: integration: sonos fields: queue_position: - name: Queue position - description: Position of the song in the queue to start playing from. selector: number: min: 0 @@ -74,15 +52,11 @@ play_queue: mode: box remove_from_queue: - name: Remove from queue - description: Removes an item from the queue. target: device: integration: sonos fields: queue_position: - name: Queue position - description: Position in the queue to remove. selector: number: min: 0 @@ -90,15 +64,11 @@ remove_from_queue: mode: box update_alarm: - name: Update alarm - description: Updates an alarm with new time and volume settings. target: device: integration: sonos fields: alarm_id: - name: Alarm ID - description: ID for the alarm to be updated. required: true selector: number: @@ -106,26 +76,18 @@ update_alarm: max: 1440 mode: box time: - name: Time - description: Set time for the alarm. example: "07:00" selector: time: volume: - name: Volume - description: Set alarm volume level. selector: number: min: 0 max: 1 step: 0.01 enabled: - name: Alarm enabled - description: Enable or disable the alarm. selector: boolean: include_linked_zones: - name: Include linked zones - description: Enable or disable including grouped rooms. selector: boolean: diff --git a/homeassistant/components/sonos/strings.json b/homeassistant/components/sonos/strings.json index 75c1b850146aa7..c5b5136e9700ad 100644 --- a/homeassistant/components/sonos/strings.json +++ b/homeassistant/components/sonos/strings.json @@ -16,5 +16,95 @@ "title": "Networking error: subscriptions failed", "description": "Falling back to polling, functionality may be limited.\n\nSonos device at {device_ip} cannot reach Home Assistant at {listener_address}.\n\nSee our [documentation]({sub_fail_url}) for more information on how to solve this issue." } + }, + "services": { + "snapshot": { + "name": "Snapshot", + "description": "Takes a snapshot of the media player.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name of entity that will be snapshot." + }, + "with_group": { + "name": "With group", + "description": "True or False. Also snapshot the group layout." + } + } + }, + "restore": { + "name": "Restore", + "description": "Restores a snapshot of the media player.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name of entity that will be restored." + }, + "with_group": { + "name": "With group", + "description": "True or False. Also restore the group layout." + } + } + }, + "set_sleep_timer": { + "name": "Set timer", + "description": "Sets a Sonos timer.", + "fields": { + "sleep_time": { + "name": "Sleep Time", + "description": "Number of seconds to set the timer." + } + } + }, + "clear_sleep_timer": { + "name": "Clear timer", + "description": "Clears a Sonos timer." + }, + "play_queue": { + "name": "Play queue", + "description": "Start playing the queue from the first item.", + "fields": { + "queue_position": { + "name": "Queue position", + "description": "Position of the song in the queue to start playing from." + } + } + }, + "remove_from_queue": { + "name": "Remove from queue", + "description": "Removes an item from the queue.", + "fields": { + "queue_position": { + "name": "Queue position", + "description": "Position in the queue to remove." + } + } + }, + "update_alarm": { + "name": "Update alarm", + "description": "Updates an alarm with new time and volume settings.", + "fields": { + "alarm_id": { + "name": "Alarm ID", + "description": "ID for the alarm to be updated." + }, + "time": { + "name": "Time", + "description": "Set time for the alarm." + }, + "volume": { + "name": "Volume", + "description": "Set alarm volume level." + }, + "enabled": { + "name": "Alarm enabled", + "description": "Enable or disable the alarm." + }, + "include_linked_zones": { + "name": "Include linked zones", + "description": "Enable or disable including grouped rooms." + } + } + } } } diff --git a/homeassistant/components/soundtouch/services.yaml b/homeassistant/components/soundtouch/services.yaml index 8270905349665b..10ae15a3cb9621 100644 --- a/homeassistant/components/soundtouch/services.yaml +++ b/homeassistant/components/soundtouch/services.yaml @@ -1,10 +1,6 @@ play_everywhere: - name: Play everywhere - description: Play on all Bose SoundTouch devices. fields: master: - name: Master - description: Name of the master entity that will coordinate the grouping. Platform dependent. It is a shortcut for creating a multi-room zone with all devices required: true selector: entity: @@ -12,20 +8,14 @@ play_everywhere: domain: media_player create_zone: - name: Create zone - description: Create a SoundTouch multi-room zone. fields: master: - name: Master - description: Name of the master entity that will coordinate the multi-room zone. Platform dependent. required: true selector: entity: integration: soundtouch domain: media_player slaves: - name: Slaves - description: Name of slaves entities to add to the new zone. required: true selector: entity: @@ -34,20 +24,14 @@ create_zone: domain: media_player add_zone_slave: - name: Add zone slave - description: Add a slave to a SoundTouch multi-room zone. fields: master: - name: Master - description: Name of the master entity that is coordinating the multi-room zone. Platform dependent. required: true selector: entity: integration: soundtouch domain: media_player slaves: - name: Slaves - description: Name of slaves entities to add to the existing zone. required: true selector: entity: @@ -56,20 +40,14 @@ add_zone_slave: domain: media_player remove_zone_slave: - name: Remove zone slave - description: Remove a slave from the SoundTouch multi-room zone. fields: master: - name: Master - description: Name of the master entity that is coordinating the multi-room zone. Platform dependent. required: true selector: entity: integration: soundtouch domain: media_player slaves: - name: Slaves - description: Name of slaves entities to remove from the existing zone. required: true selector: entity: diff --git a/homeassistant/components/soundtouch/strings.json b/homeassistant/components/soundtouch/strings.json index 7ebcd4c528572c..616a4fc5a115fd 100644 --- a/homeassistant/components/soundtouch/strings.json +++ b/homeassistant/components/soundtouch/strings.json @@ -17,5 +17,59 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" } + }, + "services": { + "play_everywhere": { + "name": "Play everywhere", + "description": "Plays on all Bose SoundTouch devices.", + "fields": { + "master": { + "name": "Master", + "description": "Name of the master entity that will coordinate the grouping. Platform dependent. It is a shortcut for creating a multi-room zone with all devices." + } + } + }, + "create_zone": { + "name": "Create zone", + "description": "Creates a SoundTouch multi-room zone.", + "fields": { + "master": { + "name": "Master", + "description": "Name of the master entity that will coordinate the multi-room zone. Platform dependent." + }, + "slaves": { + "name": "Slaves", + "description": "Name of slaves entities to add to the new zone." + } + } + }, + "add_zone_slave": { + "name": "Add zone slave", + "description": "Adds a slave to a SoundTouch multi-room zone.", + "fields": { + "master": { + "name": "Master", + "description": "Name of the master entity that is coordinating the multi-room zone. Platform dependent." + }, + "slaves": { + "name": "Slaves", + "description": "Name of slaves entities to add to the existing zone." + } + } + }, + "remove_zone_slave": { + "name": "Remove zone slave", + "description": "Removes a slave from the SoundTouch multi-room zone.", + "fields": { + "master": { + "name": "Master", + "description": "Name of the master entity that is coordinating the multi-room zone. Platform dependent." + }, + "slaves": { + "name": "Slaves", + "description": "Name of slaves entities to remove from the existing zone." + } + } + } } } diff --git a/homeassistant/components/squeezebox/services.yaml b/homeassistant/components/squeezebox/services.yaml index 4c2d34ba88b327..90f9bf2d7695f0 100644 --- a/homeassistant/components/squeezebox/services.yaml +++ b/homeassistant/components/squeezebox/services.yaml @@ -1,69 +1,47 @@ call_method: - name: Call method - description: Call a custom Squeezebox JSONRPC API. target: entity: integration: squeezebox domain: media_player fields: command: - name: Command - description: Command to pass to Logitech Media Server (p0 in the CLI documentation). required: true example: "playlist" selector: text: parameters: - name: Parameters - description: > - Array of additional parameters to pass to Logitech Media Server (p1, ..., pN in the CLI documentation). example: '["loadtracks", "album.titlesearch=Revolver"]' advanced: true selector: object: call_query: - name: Call query - description: > - Call a custom Squeezebox JSONRPC API. Result will be stored in 'query_result' attribute of the Squeezebox entity. target: entity: integration: squeezebox domain: media_player fields: command: - name: Command - description: Command to pass to Logitech Media Server (p0 in the CLI documentation). required: true example: "albums" selector: text: parameters: - name: Parameters - description: > - Array of additional parameters to pass to Logitech Media Server (p1, ..., pN in the CLI documentation). example: '["0", "20", "search:Revolver"]' advanced: true selector: object: sync: - name: Sync - description: > - Add another player to this player's sync group. If the other player is already in a sync group, it will leave it. target: entity: integration: squeezebox domain: media_player fields: other_player: - name: Other player - description: Name of the other Squeezebox player to link. required: true example: "media_player.living_room" selector: text: unsync: - name: Unsync - description: Remove this player from its sync group. target: entity: integration: squeezebox diff --git a/homeassistant/components/squeezebox/strings.json b/homeassistant/components/squeezebox/strings.json index 4ae8d69bacd4b2..13fe16aa28c3d4 100644 --- a/homeassistant/components/squeezebox/strings.json +++ b/homeassistant/components/squeezebox/strings.json @@ -27,5 +27,49 @@ "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", "no_server_found": "No LMS server found." } + }, + "services": { + "call_method": { + "name": "Call method", + "description": "Calls a custom Squeezebox JSONRPC API.", + "fields": { + "command": { + "name": "Command", + "description": "Command to pass to Logitech Media Server (p0 in the CLI documentation)." + }, + "parameters": { + "name": "Parameters", + "description": "Array of additional parameters to pass to Logitech Media Server (p1, ..., pN in the CLI documentation).\n." + } + } + }, + "call_query": { + "name": "Call query", + "description": "Calls a custom Squeezebox JSONRPC API. Result will be stored in 'query_result' attribute of the Squeezebox entity.\n.", + "fields": { + "command": { + "name": "Command", + "description": "Command to pass to Logitech Media Server (p0 in the CLI documentation)." + }, + "parameters": { + "name": "Parameters", + "description": "Array of additional parameters to pass to Logitech Media Server (p1, ..., pN in the CLI documentation).\n." + } + } + }, + "sync": { + "name": "Sync", + "description": "Adds another player to this player's sync group. If the other player is already in a sync group, it will leave it.\n.", + "fields": { + "other_player": { + "name": "Other player", + "description": "Name of the other Squeezebox player to link." + } + } + }, + "unsync": { + "name": "Unsync", + "description": "Removes this player from its sync group." + } } } diff --git a/homeassistant/components/starline/services.yaml b/homeassistant/components/starline/services.yaml index 4c3e4d360e814e..1d7041f0eb56cd 100644 --- a/homeassistant/components/starline/services.yaml +++ b/homeassistant/components/starline/services.yaml @@ -1,15 +1,7 @@ update_state: - name: Update state - description: > - Fetch the last state of the devices from the StarLine server. set_scan_interval: - name: Set scan interval - description: > - Set update frequency. fields: scan_interval: - name: Scan interval - description: Update frequency. selector: number: min: 10 @@ -17,13 +9,8 @@ set_scan_interval: step: 5 unit_of_measurement: seconds set_scan_obd_interval: - name: Set scan OBD interval - description: > - Set OBD info update frequency. fields: scan_interval: - name: Scan interval - description: Update frequency. selector: number: min: 180 diff --git a/homeassistant/components/starline/strings.json b/homeassistant/components/starline/strings.json index 10e99f9381440b..292ae55da1fff8 100644 --- a/homeassistant/components/starline/strings.json +++ b/homeassistant/components/starline/strings.json @@ -37,5 +37,31 @@ "error_auth_user": "Incorrect username or password", "error_auth_mfa": "Incorrect code" } + }, + "services": { + "update_state": { + "name": "Update state", + "description": "Fetches the last state of the devices from the StarLine server.\n." + }, + "set_scan_interval": { + "name": "Set scan interval", + "description": "Sets update frequency.", + "fields": { + "scan_interval": { + "name": "Scan interval", + "description": "Update frequency." + } + } + }, + "set_scan_obd_interval": { + "name": "Set scan OBD interval", + "description": "Sets OBD info update frequency.", + "fields": { + "scan_interval": { + "name": "Scan interval", + "description": "Update frequency." + } + } + } } } diff --git a/homeassistant/components/streamlabswater/services.yaml b/homeassistant/components/streamlabswater/services.yaml index b54c2cf15ebbee..7504a9111236f8 100644 --- a/homeassistant/components/streamlabswater/services.yaml +++ b/homeassistant/components/streamlabswater/services.yaml @@ -1,10 +1,6 @@ set_away_mode: - name: Set away mode - description: "Set the home/away mode for a Streamlabs Water Monitor." fields: away_mode: - name: Away mode - description: home or away required: true selector: select: diff --git a/homeassistant/components/streamlabswater/strings.json b/homeassistant/components/streamlabswater/strings.json new file mode 100644 index 00000000000000..56b35ab10442d4 --- /dev/null +++ b/homeassistant/components/streamlabswater/strings.json @@ -0,0 +1,14 @@ +{ + "services": { + "set_away_mode": { + "name": "Set away mode", + "description": "Sets the home/away mode for a Streamlabs Water Monitor.", + "fields": { + "away_mode": { + "name": "Away mode", + "description": "Home or away." + } + } + } + } +} diff --git a/homeassistant/components/subaru/services.yaml b/homeassistant/components/subaru/services.yaml index 58be48f9d18f26..bc760d2469ef39 100644 --- a/homeassistant/components/subaru/services.yaml +++ b/homeassistant/components/subaru/services.yaml @@ -1,14 +1,10 @@ unlock_specific_door: - name: Unlock Specific Door - description: Unlocks specific door(s) target: entity: domain: lock integration: subaru fields: door: - name: Door - description: "One of the following: 'all', 'driver', 'tailgate'" example: driver required: true selector: diff --git a/homeassistant/components/subaru/strings.json b/homeassistant/components/subaru/strings.json index abde396ba75584..2ce3c3835a64a7 100644 --- a/homeassistant/components/subaru/strings.json +++ b/homeassistant/components/subaru/strings.json @@ -46,7 +46,6 @@ "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]" } }, - "options": { "step": { "init": { @@ -57,5 +56,17 @@ } } } + }, + "services": { + "unlock_specific_door": { + "name": "Unlock specific door", + "description": "Unlocks specific door(s).", + "fields": { + "door": { + "name": "Door", + "description": "One of the following: 'all', 'driver', 'tailgate'." + } + } + } } } diff --git a/homeassistant/components/surepetcare/services.yaml b/homeassistant/components/surepetcare/services.yaml index 3c3919f5d01cbf..1d42c8fc102681 100644 --- a/homeassistant/components/surepetcare/services.yaml +++ b/homeassistant/components/surepetcare/services.yaml @@ -1,17 +1,11 @@ set_lock_state: - name: Set lock state - description: Sets lock state fields: flap_id: - name: Flap ID - description: Flap ID to lock/unlock required: true example: "123456" selector: text: lock_state: - name: Lock state - description: New lock state. required: true selector: select: @@ -22,17 +16,13 @@ set_lock_state: - "unlocked" set_pet_location: - name: Set pet location - description: Set pet location fields: pet_name: - description: Name of pet example: My_cat required: true selector: text: location: - description: Pet location (Inside or Outside) example: Inside required: true selector: diff --git a/homeassistant/components/surepetcare/strings.json b/homeassistant/components/surepetcare/strings.json index f7a539fe0e6e0d..6e1ec9643a737b 100644 --- a/homeassistant/components/surepetcare/strings.json +++ b/homeassistant/components/surepetcare/strings.json @@ -16,5 +16,35 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_account%]" } + }, + "services": { + "set_lock_state": { + "name": "Set lock state", + "description": "Sets lock state.", + "fields": { + "flap_id": { + "name": "Flap ID", + "description": "Flap ID to lock/unlock." + }, + "lock_state": { + "name": "Lock state", + "description": "New lock state." + } + } + }, + "set_pet_location": { + "name": "Set pet location", + "description": "Sets pet location.", + "fields": { + "pet_name": { + "name": "Pet name", + "description": "Name of pet." + }, + "location": { + "name": "Location", + "description": "Pet location (Inside or Outside)." + } + } + } } } diff --git a/homeassistant/components/switcher_kis/services.yaml b/homeassistant/components/switcher_kis/services.yaml index a7c3df5903e333..1dcb15fa4827b6 100644 --- a/homeassistant/components/switcher_kis/services.yaml +++ b/homeassistant/components/switcher_kis/services.yaml @@ -1,6 +1,4 @@ set_auto_off: - name: Set auto off - description: "Update Switcher device auto off setting." target: entity: integration: switcher_kis @@ -8,16 +6,12 @@ set_auto_off: device_class: switch fields: auto_off: - name: Auto off - description: "Time period string containing hours and minutes." required: true example: '"02:30"' selector: text: turn_on_with_timer: - name: Turn on with timer - description: "Turn on the Switcher device with timer." target: entity: integration: switcher_kis @@ -25,8 +19,6 @@ turn_on_with_timer: device_class: switch fields: timer_minutes: - name: Timer - description: "Time to turn on." required: true selector: number: diff --git a/homeassistant/components/switcher_kis/strings.json b/homeassistant/components/switcher_kis/strings.json index ad8f0f41ae7b29..4c4080a83943f3 100644 --- a/homeassistant/components/switcher_kis/strings.json +++ b/homeassistant/components/switcher_kis/strings.json @@ -9,5 +9,27 @@ "single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]", "no_devices_found": "[%key:common::config_flow::abort::no_devices_found%]" } + }, + "services": { + "set_auto_off": { + "name": "Set auto off", + "description": "Updates Switcher device auto off setting.", + "fields": { + "auto_off": { + "name": "Auto off", + "description": "Time period string containing hours and minutes." + } + } + }, + "turn_on_with_timer": { + "name": "Turn on with timer", + "description": "Turns on the Switcher device with timer.", + "fields": { + "timer_minutes": { + "name": "Timer", + "description": "Time to turn on." + } + } + } } } diff --git a/homeassistant/components/synology_dsm/services.yaml b/homeassistant/components/synology_dsm/services.yaml index 245d45fc8007b2..32baeec11c191c 100644 --- a/homeassistant/components/synology_dsm/services.yaml +++ b/homeassistant/components/synology_dsm/services.yaml @@ -1,23 +1,15 @@ # synology-dsm service entries description. reboot: - name: Reboot - description: Reboot the NAS. This service is deprecated and will be removed in future release. Please use the corresponding button entity. fields: serial: - name: Serial - description: serial of the NAS to reboot; required when multiple NAS are configured. example: 1NDVC86409 selector: text: shutdown: - name: Shutdown - description: Shutdown the NAS. This service is deprecated and will be removed in future release. Please use the corresponding button entity. fields: serial: - name: Serial - description: serial of the NAS to shutdown; required when multiple NAS are configured. example: 1NDVC86409 selector: text: diff --git a/homeassistant/components/synology_dsm/strings.json b/homeassistant/components/synology_dsm/strings.json index 92903b1d2aec2e..24ed1aaf568cb1 100644 --- a/homeassistant/components/synology_dsm/strings.json +++ b/homeassistant/components/synology_dsm/strings.json @@ -63,48 +63,130 @@ }, "entity": { "binary_sensor": { - "disk_below_remain_life_thr": { "name": "Below min remaining life" }, - "disk_exceed_bad_sector_thr": { "name": "Exceeded max bad sectors" }, - "status": { "name": "Security status" } + "disk_below_remain_life_thr": { + "name": "Below min remaining life" + }, + "disk_exceed_bad_sector_thr": { + "name": "Exceeded max bad sectors" + }, + "status": { + "name": "Security status" + } }, "sensor": { - "cpu_15min_load": { "name": "CPU load average (15 min)" }, - "cpu_1min_load": { "name": "CPU load average (1 min)" }, - "cpu_5min_load": { "name": "CPU load average (5 min)" }, - "cpu_other_load": { "name": "CPU utilization (other)" }, - "cpu_system_load": { "name": "CPU utilization (system)" }, - "cpu_total_load": { "name": "CPU utilization (total)" }, - "cpu_user_load": { "name": "CPU utilization (user)" }, - "disk_smart_status": { "name": "Status (smart)" }, - "disk_status": { "name": "Status" }, + "cpu_15min_load": { + "name": "CPU load average (15 min)" + }, + "cpu_1min_load": { + "name": "CPU load average (1 min)" + }, + "cpu_5min_load": { + "name": "CPU load average (5 min)" + }, + "cpu_other_load": { + "name": "CPU utilization (other)" + }, + "cpu_system_load": { + "name": "CPU utilization (system)" + }, + "cpu_total_load": { + "name": "CPU utilization (total)" + }, + "cpu_user_load": { + "name": "CPU utilization (user)" + }, + "disk_smart_status": { + "name": "Status (smart)" + }, + "disk_status": { + "name": "Status" + }, "disk_temp": { "name": "[%key:component::sensor::entity_component::temperature::name%]" }, - "memory_available_real": { "name": "Memory available (real)" }, - "memory_available_swap": { "name": "Memory available (swap)" }, - "memory_cached": { "name": "Memory cached" }, - "memory_real_usage": { "name": "Memory usage (real)" }, - "memory_size": { "name": "Memory size" }, - "memory_total_real": { "name": "Memory total (real)" }, - "memory_total_swap": { "name": "Memory total (swap)" }, - "network_down": { "name": "Download throughput" }, - "network_up": { "name": "Upload throughput" }, + "memory_available_real": { + "name": "Memory available (real)" + }, + "memory_available_swap": { + "name": "Memory available (swap)" + }, + "memory_cached": { + "name": "Memory cached" + }, + "memory_real_usage": { + "name": "Memory usage (real)" + }, + "memory_size": { + "name": "Memory size" + }, + "memory_total_real": { + "name": "Memory total (real)" + }, + "memory_total_swap": { + "name": "Memory total (swap)" + }, + "network_down": { + "name": "Download throughput" + }, + "network_up": { + "name": "Upload throughput" + }, "temperature": { "name": "[%key:component::sensor::entity_component::temperature::name%]" }, - "uptime": { "name": "Last boot" }, - "volume_disk_temp_avg": { "name": "Average disk temp" }, - "volume_disk_temp_max": { "name": "Maximum disk temp" }, - "volume_percentage_used": { "name": "Volume used" }, - "volume_size_total": { "name": "Total size" }, - "volume_size_used": { "name": "Used space" }, - "volume_status": { "name": "Status" } + "uptime": { + "name": "Last boot" + }, + "volume_disk_temp_avg": { + "name": "Average disk temp" + }, + "volume_disk_temp_max": { + "name": "Maximum disk temp" + }, + "volume_percentage_used": { + "name": "Volume used" + }, + "volume_size_total": { + "name": "Total size" + }, + "volume_size_used": { + "name": "Used space" + }, + "volume_status": { + "name": "Status" + } }, "switch": { - "home_mode": { "name": "Home mode" } + "home_mode": { + "name": "Home mode" + } }, "update": { - "update": { "name": "DSM update" } + "update": { + "name": "DSM update" + } + } + }, + "services": { + "reboot": { + "name": "Reboot", + "description": "Reboots the NAS. This service is deprecated and will be removed in future release. Please use the corresponding button entity.", + "fields": { + "serial": { + "name": "Serial", + "description": "Serial of the NAS to reboot; required when multiple NAS are configured." + } + } + }, + "shutdown": { + "name": "Shutdown", + "description": "Shutdowns the NAS. This service is deprecated and will be removed in future release. Please use the corresponding button entity.", + "fields": { + "serial": { + "name": "Serial", + "description": "Serial of the NAS to shutdown; required when multiple NAS are configured." + } + } } } } diff --git a/homeassistant/components/system_bridge/services.yaml b/homeassistant/components/system_bridge/services.yaml index d33235ffba46b0..78d6e87f2184a4 100644 --- a/homeassistant/components/system_bridge/services.yaml +++ b/homeassistant/components/system_bridge/services.yaml @@ -1,71 +1,47 @@ open_path: - name: Open Path - description: Open a file on the server using the default application. fields: bridge: - name: Bridge - description: The server to talk to. required: true selector: device: integration: system_bridge path: - name: Path - description: Path to open. required: true example: "C:\\test\\image.png" selector: text: open_url: - name: Open URL - description: Open a URL on the server using the default application. fields: bridge: - name: Bridge - description: The server to talk to. required: true selector: device: integration: system_bridge url: - name: URL - description: URL to open. required: true example: "https://www.home-assistant.io" selector: text: send_keypress: - name: Send Keyboard Keypress - description: Sends a keyboard keypress. fields: bridge: - name: Bridge - description: The server to send the command to. required: true selector: device: integration: system_bridge key: - name: Key - description: "Key to press. List available here: http://robotjs.io/docs/syntax#keys" required: true example: "audio_play" selector: text: send_text: - name: Send Keyboard Text - description: Sends text for the server to type. fields: bridge: - name: Bridge - description: The server to send the command to. required: true selector: device: integration: system_bridge text: - name: Text - description: "Text to type." required: true example: "Hello world" selector: diff --git a/homeassistant/components/system_bridge/strings.json b/homeassistant/components/system_bridge/strings.json index 209bce9078ad82..e4b2b40637cf4d 100644 --- a/homeassistant/components/system_bridge/strings.json +++ b/homeassistant/components/system_bridge/strings.json @@ -27,5 +27,63 @@ "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]", "unknown": "[%key:common::config_flow::error::unknown%]" } + }, + "services": { + "open_path": { + "name": "Open path", + "description": "Opens a file on the server using the default application.", + "fields": { + "bridge": { + "name": "Bridge", + "description": "The server to talk to." + }, + "path": { + "name": "Path", + "description": "Path to open." + } + } + }, + "open_url": { + "name": "Open URL", + "description": "Opens a URL on the server using the default application.", + "fields": { + "bridge": { + "name": "Bridge", + "description": "The server to talk to." + }, + "url": { + "name": "URL", + "description": "URL to open." + } + } + }, + "send_keypress": { + "name": "Send keyboard keypress", + "description": "Sends a keyboard keypress.", + "fields": { + "bridge": { + "name": "Bridge", + "description": "The server to send the command to." + }, + "key": { + "name": "Key", + "description": "Key to press. List available here: http://robotjs.io/docs/syntax#keys." + } + } + }, + "send_text": { + "name": "Send keyboard text", + "description": "Sends text for the server to type.", + "fields": { + "bridge": { + "name": "Bridge", + "description": "The server to send the command to." + }, + "text": { + "name": "Text", + "description": "Text to type." + } + } + } } } From 78a8f904887e461688038de187f7427a72265364 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 11 Jul 2023 15:20:41 -1000 Subject: [PATCH 068/154] Add additional tplink kasa OUI (#96383) Found on another test device --- homeassistant/components/tplink/manifest.json | 4 ++++ homeassistant/generated/dhcp.py | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/homeassistant/components/tplink/manifest.json b/homeassistant/components/tplink/manifest.json index 0a9b0254f91d0c..581360050535f9 100644 --- a/homeassistant/components/tplink/manifest.json +++ b/homeassistant/components/tplink/manifest.json @@ -143,6 +143,10 @@ { "hostname": "k[lp]*", "macaddress": "54AF97*" + }, + { + "hostname": "k[lp]*", + "macaddress": "AC15A2*" } ], "documentation": "https://www.home-assistant.io/integrations/tplink", diff --git a/homeassistant/generated/dhcp.py b/homeassistant/generated/dhcp.py index 05b53acba5ff84..63a0bb43d2aa1c 100644 --- a/homeassistant/generated/dhcp.py +++ b/homeassistant/generated/dhcp.py @@ -765,6 +765,11 @@ "hostname": "k[lp]*", "macaddress": "54AF97*", }, + { + "domain": "tplink", + "hostname": "k[lp]*", + "macaddress": "AC15A2*", + }, { "domain": "tuya", "macaddress": "105A17*", From 8d360611d1bb9046295340d6b8e51f00648ae786 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 07:36:51 +0200 Subject: [PATCH 069/154] Migrate integration services (W-Z) to support translations (#96381) --- .../components/wake_on_lan/services.yaml | 8 - .../components/wake_on_lan/strings.json | 22 ++ .../components/webostv/services.yaml | 25 -- homeassistant/components/webostv/strings.json | 48 ++++ homeassistant/components/wemo/services.yaml | 6 - homeassistant/components/wemo/strings.json | 16 ++ .../components/wilight/services.yaml | 14 - homeassistant/components/wilight/strings.json | 36 +++ homeassistant/components/wled/services.yaml | 16 -- homeassistant/components/wled/strings.json | 38 +++ .../components/xiaomi_aqara/services.yaml | 28 -- .../components/xiaomi_aqara/strings.json | 54 ++++ .../components/xiaomi_miio/services.yaml | 98 ------- .../components/xiaomi_miio/strings.json | 266 ++++++++++++++++++ homeassistant/components/yamaha/services.yaml | 14 - homeassistant/components/yamaha/strings.json | 38 +++ .../components/yeelight/services.yaml | 95 ++----- .../components/yeelight/strings.json | 133 +++++++++ .../components/zoneminder/services.yaml | 4 - .../components/zoneminder/strings.json | 14 + 20 files changed, 686 insertions(+), 287 deletions(-) create mode 100644 homeassistant/components/wake_on_lan/strings.json create mode 100644 homeassistant/components/yamaha/strings.json create mode 100644 homeassistant/components/zoneminder/strings.json diff --git a/homeassistant/components/wake_on_lan/services.yaml b/homeassistant/components/wake_on_lan/services.yaml index ea374a88b8f196..48d3df5c4f952f 100644 --- a/homeassistant/components/wake_on_lan/services.yaml +++ b/homeassistant/components/wake_on_lan/services.yaml @@ -1,23 +1,15 @@ send_magic_packet: - name: Send magic packet - description: Send a 'magic packet' to wake up a device with 'Wake-On-LAN' capabilities. fields: mac: - name: MAC address - description: MAC address of the device to wake up. required: true example: "aa:bb:cc:dd:ee:ff" selector: text: broadcast_address: - name: Broadcast address - description: Broadcast IP where to send the magic packet. example: 192.168.255.255 selector: text: broadcast_port: - name: Broadcast port - description: Port where to send the magic packet. default: 9 selector: number: diff --git a/homeassistant/components/wake_on_lan/strings.json b/homeassistant/components/wake_on_lan/strings.json new file mode 100644 index 00000000000000..8395bc7503a6c4 --- /dev/null +++ b/homeassistant/components/wake_on_lan/strings.json @@ -0,0 +1,22 @@ +{ + "services": { + "send_magic_packet": { + "name": "Send magic packet", + "description": "Sends a 'magic packet' to wake up a device with 'Wake-On-LAN' capabilities.", + "fields": { + "mac": { + "name": "MAC address", + "description": "MAC address of the device to wake up." + }, + "broadcast_address": { + "name": "Broadcast address", + "description": "Broadcast IP where to send the magic packet." + }, + "broadcast_port": { + "name": "Broadcast port", + "description": "Port where to send the magic packet." + } + } + } + } +} diff --git a/homeassistant/components/webostv/services.yaml b/homeassistant/components/webostv/services.yaml index 1985857d128bf8..c3297dd8902e32 100644 --- a/homeassistant/components/webostv/services.yaml +++ b/homeassistant/components/webostv/services.yaml @@ -1,52 +1,33 @@ # Describes the format for available webostv services button: - name: Button - description: "Send a button press command." fields: entity_id: - name: Entity - description: Name(s) of the webostv entities where to run the API method. required: true selector: entity: integration: webostv domain: media_player button: - name: Button - description: >- - Name of the button to press. Known possible values are - LEFT, RIGHT, DOWN, UP, HOME, MENU, BACK, ENTER, DASH, INFO, ASTERISK, CC, EXIT, - MUTE, RED, GREEN, BLUE, YELLOW, VOLUMEUP, VOLUMEDOWN, CHANNELUP, CHANNELDOWN, - PLAY, PAUSE, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 required: true example: "LEFT" selector: text: command: - name: Command - description: "Send a command." fields: entity_id: - name: Entity - description: Name(s) of the webostv entities where to run the API method. required: true selector: entity: integration: webostv domain: media_player command: - name: Command - description: Endpoint of the command. required: true example: "system.launcher/open" selector: text: payload: - name: Payload - description: >- - An optional payload to provide to the endpoint in the format of key value pair(s). example: >- target: https://www.google.com advanced: true @@ -54,20 +35,14 @@ command: object: select_sound_output: - name: Select Sound Output - description: "Send the TV the command to change sound output." fields: entity_id: - name: Entity - description: Name(s) of the webostv entities to change sound output on. required: true selector: entity: integration: webostv domain: media_player sound_output: - name: Sound Output - description: Name of the sound output to switch to. required: true example: "external_speaker" selector: diff --git a/homeassistant/components/webostv/strings.json b/homeassistant/components/webostv/strings.json index c623effe22b6b1..985edb05645a5a 100644 --- a/homeassistant/components/webostv/strings.json +++ b/homeassistant/components/webostv/strings.json @@ -48,5 +48,53 @@ "trigger_type": { "webostv.turn_on": "Device is requested to turn on" } + }, + "services": { + "button": { + "name": "Button", + "description": "Sends a button press command.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name(s) of the webostv entities where to run the API method." + }, + "button": { + "name": "Button", + "description": "Name of the button to press. Known possible values are LEFT, RIGHT, DOWN, UP, HOME, MENU, BACK, ENTER, DASH, INFO, ASTERISK, CC, EXIT, MUTE, RED, GREEN, BLUE, YELLOW, VOLUMEUP, VOLUMEDOWN, CHANNELUP, CHANNELDOWN, PLAY, PAUSE, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9." + } + } + }, + "command": { + "name": "Command", + "description": "Sends a command.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name(s) of the webostv entities where to run the API method." + }, + "command": { + "name": "Command", + "description": "Endpoint of the command." + }, + "payload": { + "name": "Payload", + "description": "An optional payload to provide to the endpoint in the format of key value pair(s)." + } + } + }, + "select_sound_output": { + "name": "Select sound output", + "description": "Sends the TV the command to change sound output.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name(s) of the webostv entities to change sound output on." + }, + "sound_output": { + "name": "Sound output", + "description": "Name of the sound output to switch to." + } + } + } } } diff --git a/homeassistant/components/wemo/services.yaml b/homeassistant/components/wemo/services.yaml index 58305798cf9194..59f38ca77a0a09 100644 --- a/homeassistant/components/wemo/services.yaml +++ b/homeassistant/components/wemo/services.yaml @@ -1,14 +1,10 @@ set_humidity: - name: Set humidity - description: Set the target humidity of WeMo humidifier devices. target: entity: integration: wemo domain: fan fields: target_humidity: - name: Target humidity - description: Target humidity. required: true selector: number: @@ -18,8 +14,6 @@ set_humidity: unit_of_measurement: "%" reset_filter_life: - name: Reset filter life - description: Reset the WeMo Humidifier's filter life to 100%. target: entity: integration: wemo diff --git a/homeassistant/components/wemo/strings.json b/homeassistant/components/wemo/strings.json index b218f7589853a7..66fa656ebfe6b4 100644 --- a/homeassistant/components/wemo/strings.json +++ b/homeassistant/components/wemo/strings.json @@ -28,5 +28,21 @@ "trigger_type": { "long_press": "Wemo button was pressed for 2 seconds" } + }, + "services": { + "set_humidity": { + "name": "Set humidity", + "description": "Sets the target humidity of WeMo humidifier devices.", + "fields": { + "target_humidity": { + "name": "Target humidity", + "description": "Target humidity." + } + } + }, + "reset_filter_life": { + "name": "Reset filter life", + "description": "Resets the WeMo Humidifier's filter life to 100%." + } } } diff --git a/homeassistant/components/wilight/services.yaml b/homeassistant/components/wilight/services.yaml index b6c538bf9fb749..044a46784ef3b1 100644 --- a/homeassistant/components/wilight/services.yaml +++ b/homeassistant/components/wilight/services.yaml @@ -1,31 +1,17 @@ set_watering_time: - name: Set watering time - description: Sets time for watering target: fields: watering_time: - name: Duration - description: Duration for this irrigation to be turned on. example: 30 set_pause_time: - name: Set pause time - description: Sets time to pause. target: fields: pause_time: - name: Duration - description: Duration for this irrigation to be paused. example: 24 set_trigger: - name: Set trigger - description: Set the trigger to use. target: fields: trigger_index: - name: Trigger index - description: Index of Trigger from 1 to 4 example: "1" trigger: - name: Trigger rules - description: Configuration of trigger. example: "'12707001'" diff --git a/homeassistant/components/wilight/strings.json b/homeassistant/components/wilight/strings.json index 0449a900c29ead..a287104e7adb5c 100644 --- a/homeassistant/components/wilight/strings.json +++ b/homeassistant/components/wilight/strings.json @@ -11,5 +11,41 @@ "not_supported_device": "This WiLight is currently not supported", "not_wilight_device": "This Device is not WiLight" } + }, + "services": { + "set_watering_time": { + "name": "Set watering time", + "description": "Sets time for watering.", + "fields": { + "watering_time": { + "name": "Duration", + "description": "Duration for this irrigation to be turned on." + } + } + }, + "set_pause_time": { + "name": "Set pause time", + "description": "Sets time to pause.", + "fields": { + "pause_time": { + "name": "Duration", + "description": "Duration for this irrigation to be paused." + } + } + }, + "set_trigger": { + "name": "Set trigger", + "description": "Sets the trigger to use.", + "fields": { + "trigger_index": { + "name": "Trigger index", + "description": "Index of Trigger from 1 to 4." + }, + "trigger": { + "name": "Trigger rules", + "description": "Configuration of trigger." + } + } + } } } diff --git a/homeassistant/components/wled/services.yaml b/homeassistant/components/wled/services.yaml index 9ca73fac0a3e1c..40170fd54e98e9 100644 --- a/homeassistant/components/wled/services.yaml +++ b/homeassistant/components/wled/services.yaml @@ -1,55 +1,39 @@ effect: - name: Set effect - description: Control the effect settings of WLED. target: entity: integration: wled domain: light fields: effect: - name: Effect - description: Name or ID of the WLED light effect. example: "Rainbow" selector: text: intensity: - name: Effect intensity - description: Intensity of the effect. Number between 0 and 255. selector: number: min: 0 max: 255 palette: - name: Color palette - description: Name or ID of the WLED light palette. example: "Tiamat" selector: text: speed: - name: Effect speed - description: Speed of the effect. selector: number: min: 0 max: 255 reverse: - name: Reverse effect - description: Reverse the effect. Either true to reverse or false otherwise. default: false selector: boolean: preset: - name: Set preset (deprecated) - description: Set a preset for the WLED device. target: entity: integration: wled domain: light fields: preset: - name: Preset ID - description: ID of the WLED preset selector: number: min: -1 diff --git a/homeassistant/components/wled/strings.json b/homeassistant/components/wled/strings.json index eed62ab04994a1..9fc6573b112d25 100644 --- a/homeassistant/components/wled/strings.json +++ b/homeassistant/components/wled/strings.json @@ -41,5 +41,43 @@ } } } + }, + "services": { + "effect": { + "name": "Set effect", + "description": "Controls the effect settings of WLED.", + "fields": { + "effect": { + "name": "Effect", + "description": "Name or ID of the WLED light effect." + }, + "intensity": { + "name": "Effect intensity", + "description": "Intensity of the effect. Number between 0 and 255." + }, + "palette": { + "name": "Color palette", + "description": "Name or ID of the WLED light palette." + }, + "speed": { + "name": "Effect speed", + "description": "Speed of the effect." + }, + "reverse": { + "name": "Reverse effect", + "description": "Reverse the effect. Either true to reverse or false otherwise." + } + } + }, + "preset": { + "name": "Set preset (deprecated)", + "description": "Sets a preset for the WLED device.", + "fields": { + "preset": { + "name": "Preset ID", + "description": "ID of the WLED preset." + } + } + } } } diff --git a/homeassistant/components/xiaomi_aqara/services.yaml b/homeassistant/components/xiaomi_aqara/services.yaml index 75a9b9156c1590..dcf79ebc215124 100644 --- a/homeassistant/components/xiaomi_aqara/services.yaml +++ b/homeassistant/components/xiaomi_aqara/services.yaml @@ -1,70 +1,42 @@ add_device: - name: Add device - description: - Enables the join permission of the Xiaomi Aqara Gateway for 30 seconds. - A new device can be added afterwards by pressing the pairing button once. fields: gw_mac: - name: Gateway MAC - description: MAC address of the Xiaomi Aqara Gateway. required: true example: 34ce00880088 selector: text: play_ringtone: - name: play ringtone - description: - Play a specific ringtone. The version of the gateway firmware must - be 1.4.1_145 at least. fields: gw_mac: - name: Gateway MAC - description: MAC address of the Xiaomi Aqara Gateway. required: true example: 34ce00880088 selector: text: ringtone_id: - name: Ringtone ID - description: One of the allowed ringtone ids. required: true example: 8 selector: text: ringtone_vol: - name: Ringtone volume - description: The volume in percent. selector: number: min: 0 max: 100 remove_device: - name: Remove device - description: - Removes a specific device. The removal is required if a device shall - be paired with another gateway. fields: device_id: - name: Device ID - description: Hardware address of the device to remove. required: true example: 158d0000000000 selector: text: gw_mac: - name: Gateway MAC - description: MAC address of the Xiaomi Aqara Gateway. required: true example: 34ce00880088 selector: text: stop_ringtone: - name: Stop ringtone - description: Stops a playing ringtone immediately. fields: gw_mac: - name: Gateway MAC - description: MAC address of the Xiaomi Aqara Gateway. required: true example: 34ce00880088 selector: diff --git a/homeassistant/components/xiaomi_aqara/strings.json b/homeassistant/components/xiaomi_aqara/strings.json index 63fb48542c9311..0944c91fd830f4 100644 --- a/homeassistant/components/xiaomi_aqara/strings.json +++ b/homeassistant/components/xiaomi_aqara/strings.json @@ -37,5 +37,59 @@ "already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]", "not_xiaomi_aqara": "Not a Xiaomi Aqara Gateway, discovered device did not match known gateways" } + }, + "services": { + "add_device": { + "name": "Add device", + "description": "Enables the join permission of the Xiaomi Aqara Gateway for 30 seconds. A new device can be added afterwards by pressing the pairing button once.", + "fields": { + "gw_mac": { + "name": "Gateway MAC", + "description": "MAC address of the Xiaomi Aqara Gateway." + } + } + }, + "play_ringtone": { + "name": "Play ringtone", + "description": "Plays a specific ringtone. The version of the gateway firmware must be 1.4.1_145 at least.", + "fields": { + "gw_mac": { + "name": "Gateway MAC", + "description": "MAC address of the Xiaomi Aqara Gateway." + }, + "ringtone_id": { + "name": "Ringtone ID", + "description": "One of the allowed ringtone ids." + }, + "ringtone_vol": { + "name": "Ringtone volume", + "description": "The volume in percent." + } + } + }, + "remove_device": { + "name": "Remove device", + "description": "Removes a specific device. The removal is required if a device shall be paired with another gateway.", + "fields": { + "device_id": { + "name": "Device ID", + "description": "Hardware address of the device to remove." + }, + "gw_mac": { + "name": "Gateway MAC", + "description": "MAC address of the Xiaomi Aqara Gateway." + } + } + }, + "stop_ringtone": { + "name": "Stop ringtone", + "description": "Stops a playing ringtone immediately.", + "fields": { + "gw_mac": { + "name": "Gateway MAC", + "description": "MAC address of the Xiaomi Aqara Gateway." + } + } + } } } diff --git a/homeassistant/components/xiaomi_miio/services.yaml b/homeassistant/components/xiaomi_miio/services.yaml index e1cf03ba4ee1e8..0b3bd6435e414d 100644 --- a/homeassistant/components/xiaomi_miio/services.yaml +++ b/homeassistant/components/xiaomi_miio/services.yaml @@ -1,27 +1,19 @@ fan_reset_filter: - name: Fan reset filter - description: Reset the filter lifetime and usage. fields: entity_id: - description: Name of the xiaomi miio entity. selector: entity: integration: xiaomi_miio domain: fan fan_set_extra_features: - name: Fan set extra features - description: Manipulates a storage register which advertises extra features. The Mi Home app evaluates the value. A feature called "turbo mode" is unlocked in the app on value 1. fields: entity_id: - description: Name of the xiaomi miio entity. selector: entity: integration: xiaomi_miio domain: fan features: - name: Features - description: Integer, known values are 0 (default) and 1 (turbo mode). required: true selector: number: @@ -29,18 +21,13 @@ fan_set_extra_features: max: 1 light_set_scene: - name: Light set scene - description: Set a fixed scene. fields: entity_id: - description: Name of the light entity. selector: entity: integration: xiaomi_miio domain: light scene: - name: Scene - description: Number of the fixed scene. required: true selector: number: @@ -48,108 +35,79 @@ light_set_scene: max: 6 light_set_delayed_turn_off: - name: Light set delayed turn off - description: Delayed turn off. fields: entity_id: - description: Name of the light entity. selector: entity: integration: xiaomi_miio domain: light time_period: - name: Time period - description: Time period for the delayed turn off. required: true example: "5, '0:05', {'minutes': 5}" selector: object: light_reminder_on: - name: Light reminder on - description: Enable the eye fatigue reminder/notification (EYECARE SMART LAMP 2 ONLY). fields: entity_id: - description: "Name of the entity to act on." selector: entity: integration: xiaomi_miio domain: light light_reminder_off: - name: Light reminder off - description: Disable the eye fatigue reminder/notification (EYECARE SMART LAMP 2 ONLY). fields: entity_id: - description: "Name of the entity to act on." selector: entity: integration: xiaomi_miio domain: light light_night_light_mode_on: - name: Night light mode on - description: Turn the eyecare mode on (EYECARE SMART LAMP 2 ONLY). fields: entity_id: - description: "Name of the entity to act on." selector: entity: integration: xiaomi_miio domain: light light_night_light_mode_off: - name: Night light mode off - description: Turn the eyecare mode fan_set_dry_off (EYECARE SMART LAMP 2 ONLY). fields: entity_id: - description: "Name of the entity to act on." selector: entity: integration: xiaomi_miio domain: light light_eyecare_mode_on: - name: Light eyecare mode on - description: Enable the eye fatigue reminder/notification (EYECARE SMART LAMP 2 ONLY). fields: entity_id: - description: "Name of the entity to act on." selector: entity: integration: xiaomi_miio domain: light light_eyecare_mode_off: - name: Light eyecare mode off - description: Disable the eye fatigue reminder/notification (EYECARE SMART LAMP 2 ONLY). fields: entity_id: - description: "Name of the entity to act on." selector: entity: integration: xiaomi_miio domain: light remote_learn_command: - name: Remote learn command - description: 'Learn an IR command, press "Call Service", point the remote at the IR device, and the learned command will be shown as a notification in Overview.' target: entity: integration: xiaomi_miio domain: remote fields: slot: - name: Slot - description: "Define the slot used to save the IR command." default: 1 selector: number: min: 1 max: 1000000 timeout: - name: Timeout - description: "Define the timeout, before which the command must be learned." default: 10 selector: number: @@ -158,56 +116,41 @@ remote_learn_command: unit_of_measurement: seconds remote_set_led_on: - name: Remote set LED on - description: "Turn on blue LED." target: entity: integration: xiaomi_miio domain: remote remote_set_led_off: - name: Remote set LED off - description: "Turn off blue LED." target: entity: integration: xiaomi_miio domain: remote switch_set_wifi_led_on: - name: Switch set Wi-fi LED on - description: Turn the wifi led on. fields: entity_id: - description: Name of the xiaomi miio entity. selector: entity: integration: xiaomi_miio domain: switch switch_set_wifi_led_off: - name: Switch set Wi-fi LED off - description: Turn the wifi led off. fields: entity_id: - description: Name of the xiaomi miio entity. selector: entity: integration: xiaomi_miio domain: switch switch_set_power_price: - name: Switch set power price - description: Set the power price. fields: entity_id: - description: Name of the xiaomi miio entity. selector: entity: integration: xiaomi_miio domain: switch mode: - name: Mode - description: Power price. required: true selector: number: @@ -215,18 +158,13 @@ switch_set_power_price: max: 999 switch_set_power_mode: - name: Switch set power mode - description: Set the power mode. fields: entity_id: - description: Name of the xiaomi miio entity. selector: entity: integration: xiaomi_miio domain: switch mode: - name: Mode - description: Power mode. required: true selector: select: @@ -235,48 +173,36 @@ switch_set_power_mode: - "normal" vacuum_remote_control_start: - name: Vacuum remote control start - description: Start remote control of the vacuum cleaner. You can then move it with `remote_control_move`, when done call `remote_control_stop`. target: entity: integration: xiaomi_miio domain: vacuum vacuum_remote_control_stop: - name: Vacuum remote control stop - description: Stop remote control mode of the vacuum cleaner. target: entity: integration: xiaomi_miio domain: vacuum vacuum_remote_control_move: - name: Vacuum remote control move - description: Remote control the vacuum cleaner, make sure you first set it in remote control mode with `remote_control_start`. target: entity: integration: xiaomi_miio domain: vacuum fields: velocity: - name: Velocity - description: Speed. selector: number: min: -0.29 max: 0.29 step: 0.01 rotation: - name: Rotation - description: Rotation, between -179 degrees and 179 degrees. selector: number: min: -179 max: 179 unit_of_measurement: "°" duration: - name: Duration - description: Duration of the movement. selector: number: min: 1 @@ -284,32 +210,24 @@ vacuum_remote_control_move: unit_of_measurement: seconds vacuum_remote_control_move_step: - name: Vacuum remote control move step - description: Remote control the vacuum cleaner, only makes one move and then stops. target: entity: integration: xiaomi_miio domain: vacuum fields: velocity: - name: Velocity - description: Speed. selector: number: min: -0.29 max: 0.29 step: 0.01 rotation: - name: Rotation - description: Rotation. selector: number: min: -179 max: 179 unit_of_measurement: "°" duration: - name: Duration - description: Duration of the movement. selector: number: min: 1 @@ -317,59 +235,43 @@ vacuum_remote_control_move_step: unit_of_measurement: seconds vacuum_clean_zone: - name: Vacuum clean zone - description: Start the cleaning operation in the selected areas for the number of repeats indicated. target: entity: integration: xiaomi_miio domain: vacuum fields: zone: - name: Zone - description: Array of zones. Each zone is an array of 4 integer values. example: "[[23510,25311,25110,26362]]" selector: object: repeats: - name: Repeats - description: Number of cleaning repeats for each zone. selector: number: min: 1 max: 3 vacuum_goto: - name: Vacuum go to - description: Go to the specified coordinates. target: entity: integration: xiaomi_miio domain: vacuum fields: x_coord: - name: X coordinate - description: x-coordinate. example: 27500 selector: text: y_coord: - name: Y coordinate - description: y-coordinate. example: 32000 selector: text: vacuum_clean_segment: - name: Vacuum clean segment - description: Start cleaning of the specified segment(s). target: entity: integration: xiaomi_miio domain: vacuum fields: segments: - name: Segments - description: Segments. example: "[1,2]" selector: object: diff --git a/homeassistant/components/xiaomi_miio/strings.json b/homeassistant/components/xiaomi_miio/strings.json index 15c89498bc7b45..578d2a96ff83f4 100644 --- a/homeassistant/components/xiaomi_miio/strings.json +++ b/homeassistant/components/xiaomi_miio/strings.json @@ -94,5 +94,271 @@ } } } + }, + "services": { + "fan_reset_filter": { + "name": "Fan reset filter", + "description": "Resets the filter lifetime and usage.", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Name of the xiaomi miio entity." + } + } + }, + "fan_set_extra_features": { + "name": "Fan set extra features", + "description": "Manipulates a storage register which advertises extra features. The Mi Home app evaluates the value. A feature called \"turbo mode\" is unlocked in the app on value 1.", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Name of the xiaomi miio entity." + }, + "features": { + "name": "Features", + "description": "Integer, known values are 0 (default) and 1 (turbo mode)." + } + } + }, + "light_set_scene": { + "name": "Light set scene", + "description": "Sets a fixed scene.", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Name of the light entity." + }, + "scene": { + "name": "Scene", + "description": "Number of the fixed scene." + } + } + }, + "light_set_delayed_turn_off": { + "name": "Light set delayed turn off", + "description": "Delayed turn off.", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Name of the light entity." + }, + "time_period": { + "name": "Time period", + "description": "Time period for the delayed turn off." + } + } + }, + "light_reminder_on": { + "name": "Light reminder on", + "description": "Enables the eye fatigue reminder/notification (EYECARE SMART LAMP 2 ONLY).", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Name of the entity to act on." + } + } + }, + "light_reminder_off": { + "name": "Light reminder off", + "description": "Disables the eye fatigue reminder/notification (EYECARE SMART LAMP 2 ONLY).", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Name of the entity to act on." + } + } + }, + "light_night_light_mode_on": { + "name": "Night light mode on", + "description": "Turns the eyecare mode on (EYECARE SMART LAMP 2 ONLY).", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Name of the entity to act on." + } + } + }, + "light_night_light_mode_off": { + "name": "Night light mode off", + "description": "Turns the eyecare mode fan_set_dry_off (EYECARE SMART LAMP 2 ONLY).", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Name of the entity to act on." + } + } + }, + "light_eyecare_mode_on": { + "name": "Light eyecare mode on", + "description": "Enables the eye fatigue reminder/notification (EYECARE SMART LAMP 2 ONLY).", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Name of the entity to act on." + } + } + }, + "light_eyecare_mode_off": { + "name": "Light eyecare mode off", + "description": "Disables the eye fatigue reminder/notification (EYECARE SMART LAMP 2 ONLY).", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Name of the entity to act on." + } + } + }, + "remote_learn_command": { + "name": "Remote learn command", + "description": "Learns an IR command, press \"Call Service\", point the remote at the IR device, and the learned command will be shown as a notification in Overview.", + "fields": { + "slot": { + "name": "Slot", + "description": "Define the slot used to save the IR command." + }, + "timeout": { + "name": "Timeout", + "description": "Define the timeout, before which the command must be learned." + } + } + }, + "remote_set_led_on": { + "name": "Remote set LED on", + "description": "Turns on blue LED." + }, + "remote_set_led_off": { + "name": "Remote set LED off", + "description": "Turns off blue LED." + }, + "switch_set_wifi_led_on": { + "name": "Switch set Wi-Fi LED on", + "description": "Turns the wifi led on.", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Name of the xiaomi miio entity." + } + } + }, + "switch_set_wifi_led_off": { + "name": "Switch set Wi-Fi LED off", + "description": "Turn the Wi-Fi led off.", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Name of the xiaomi miio entity." + } + } + }, + "switch_set_power_price": { + "name": "Switch set power price", + "description": "Sets the power price.", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Name of the xiaomi miio entity." + }, + "mode": { + "name": "Mode", + "description": "Power price." + } + } + }, + "switch_set_power_mode": { + "name": "Switch set power mode", + "description": "Sets the power mode.", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Name of the xiaomi miio entity." + }, + "mode": { + "name": "Mode", + "description": "Power mode." + } + } + }, + "vacuum_remote_control_start": { + "name": "Vacuum remote control start", + "description": "Starts remote control of the vacuum cleaner. You can then move it with `remote_control_move`, when done call `remote_control_stop`." + }, + "vacuum_remote_control_stop": { + "name": "Vacuum remote control stop", + "description": "Stops remote control mode of the vacuum cleaner." + }, + "vacuum_remote_control_move": { + "name": "Vacuum remote control move", + "description": "Remote controls the vacuum cleaner, make sure you first set it in remote control mode with `remote_control_start`.", + "fields": { + "velocity": { + "name": "Velocity", + "description": "Speed." + }, + "rotation": { + "name": "Rotation", + "description": "Rotation, between -179 degrees and 179 degrees." + }, + "duration": { + "name": "Duration", + "description": "Duration of the movement." + } + } + }, + "vacuum_remote_control_move_step": { + "name": "Vacuum remote control move step", + "description": "Remote controls the vacuum cleaner, only makes one move and then stops.", + "fields": { + "velocity": { + "name": "Velocity", + "description": "Speed." + }, + "rotation": { + "name": "Rotation", + "description": "Rotation." + }, + "duration": { + "name": "Duration", + "description": "Duration of the movement." + } + } + }, + "vacuum_clean_zone": { + "name": "Vacuum clean zone", + "description": "Starts the cleaning operation in the selected areas for the number of repeats indicated.", + "fields": { + "zone": { + "name": "Zone", + "description": "Array of zones. Each zone is an array of 4 integer values." + }, + "repeats": { + "name": "Repeats", + "description": "Number of cleaning repeats for each zone." + } + } + }, + "vacuum_goto": { + "name": "Vacuum go to", + "description": "Go to the specified coordinates.", + "fields": { + "x_coord": { + "name": "X coordinate", + "description": "X-coordinate." + }, + "y_coord": { + "name": "Y coordinate", + "description": "Y-coordinate." + } + } + }, + "vacuum_clean_segment": { + "name": "Vacuum clean segment", + "description": "Starts cleaning of the specified segment(s).", + "fields": { + "segments": { + "name": "Segments", + "description": "Segments." + } + } + } } } diff --git a/homeassistant/components/yamaha/services.yaml b/homeassistant/components/yamaha/services.yaml index 8d25d5925c13db..705f2996a3cd8d 100644 --- a/homeassistant/components/yamaha/services.yaml +++ b/homeassistant/components/yamaha/services.yaml @@ -1,49 +1,35 @@ enable_output: - name: Enable output - description: Enable or disable an output port target: entity: integration: yamaha domain: media_player fields: port: - name: Port - description: Name of port to enable/disable. required: true example: "hdmi1" selector: text: enabled: - name: Enabled - description: Indicate if port should be enabled or not. required: true selector: boolean: menu_cursor: - name: Menu cursor - description: Control the cursor in a menu target: entity: integration: yamaha domain: media_player fields: cursor: - name: Cursor - description: Name of the cursor key to press ('up', 'down', 'left', 'right', 'select', 'return') example: down selector: text: select_scene: - name: Select scene - description: "Select a scene on the receiver" target: entity: integration: yamaha domain: media_player fields: scene: - name: Scene - description: Name of the scene. Standard for RX-V437 is 'BD/DVD Movie Viewing', 'TV Viewing', 'NET Audio Listening' or 'Radio Listening' required: true example: "TV Viewing" selector: diff --git a/homeassistant/components/yamaha/strings.json b/homeassistant/components/yamaha/strings.json new file mode 100644 index 00000000000000..0896f43b1b515e --- /dev/null +++ b/homeassistant/components/yamaha/strings.json @@ -0,0 +1,38 @@ +{ + "services": { + "enable_output": { + "name": "Enable output", + "description": "Enables or disables an output port.", + "fields": { + "port": { + "name": "Port", + "description": "Name of port to enable/disable." + }, + "enabled": { + "name": "Enabled", + "description": "Indicate if port should be enabled or not." + } + } + }, + "menu_cursor": { + "name": "Menu cursor", + "description": "Controls the cursor in a menu.", + "fields": { + "cursor": { + "name": "Cursor", + "description": "Name of the cursor key to press ('up', 'down', 'left', 'right', 'select', 'return')." + } + } + }, + "select_scene": { + "name": "Select scene", + "description": "Selects a scene on the receiver.", + "fields": { + "scene": { + "name": "Scene", + "description": "Name of the scene. Standard for RX-V437 is 'BD/DVD Movie Viewing', 'TV Viewing', 'NET Audio Listening' or 'Radio Listening'." + } + } + } + } +} diff --git a/homeassistant/components/yeelight/services.yaml b/homeassistant/components/yeelight/services.yaml index d7850b34607546..ccfd46ef6804bb 100644 --- a/homeassistant/components/yeelight/services.yaml +++ b/homeassistant/components/yeelight/services.yaml @@ -1,85 +1,60 @@ set_mode: - name: Set mode - description: Set a operation mode. target: entity: integration: yeelight domain: light fields: mode: - name: Mode - description: Operation mode. required: true selector: select: options: - - label: "Color Flow" - value: "color_flow" - - label: "HSV" - value: "hsv" - - label: "Last" - value: "last" - - label: "Moonlight" - value: "moonlight" - - label: "Normal" - value: "normal" - - label: "RGB" - value: "rgb" + - "color_flow" + - "hsv" + - "last" + - "moonlight" + - "normal" + - "rgb" + translation_key: mode set_color_scene: - name: Set color scene - description: Changes the light to the specified RGB color and brightness. If the light is off, it will be turned on. target: entity: integration: yeelight domain: light fields: rgb_color: - name: RGB color - description: Color for the light in RGB-format. example: "[255, 100, 100]" selector: object: brightness: - name: Brightness - description: The brightness value to set. selector: number: min: 0 max: 100 unit_of_measurement: "%" set_hsv_scene: - name: Set HSV scene - description: Changes the light to the specified HSV color and brightness. If the light is off, it will be turned on. target: entity: integration: yeelight domain: light fields: hs_color: - name: Hue/sat color - description: Color for the light in hue/sat format. Hue is 0-359 and Sat is 0-100. example: "[300, 70]" selector: object: brightness: - name: Brightness - description: The brightness value to set. selector: number: min: 0 max: 100 unit_of_measurement: "%" set_color_temp_scene: - name: Set color temperature scene - description: Changes the light to the specified color temperature. If the light is off, it will be turned on. target: entity: integration: yeelight domain: light fields: kelvin: - name: Kelvin - description: Color temperature for the light in Kelvin. selector: number: min: 1700 @@ -87,118 +62,90 @@ set_color_temp_scene: step: 100 unit_of_measurement: K brightness: - name: Brightness - description: The brightness value to set. selector: number: min: 0 max: 100 unit_of_measurement: "%" set_color_flow_scene: - name: Set color flow scene - description: starts a color flow. If the light is off, it will be turned on. target: entity: integration: yeelight domain: light fields: count: - name: Count - description: The number of times to run this flow (0 to run forever). default: 0 selector: number: min: 0 max: 100 action: - name: Action - description: The action to take after the flow stops. default: "recover" selector: select: options: - - label: "Off" - value: "off" - - label: "Recover" - value: "recover" - - label: "Stay" - value: "stay" + - "off" + - "recover" + - "stay" + translation_key: action transitions: - name: Transitions - description: Array of transitions, for desired effect. Examples https://yeelight.readthedocs.io/en/stable/flow.html - example: '[{ "TemperatureTransition": [1900, 1000, 80] }, { "TemperatureTransition": [1900, 1000, 10] }]' + example: + '[{ "TemperatureTransition": [1900, 1000, 80] }, { "TemperatureTransition": + [1900, 1000, 10] }]' selector: object: set_auto_delay_off_scene: - name: Set auto delay off scene - description: Turns the light on to the specified brightness and sets a timer to turn it back off after the given number of minutes. If the light is off, Set a color scene, if light is off, it will be turned on. target: entity: integration: yeelight domain: light fields: minutes: - name: Minutes - description: The time to wait before automatically turning the light off. selector: number: min: 1 max: 60 unit_of_measurement: minutes brightness: - name: Brightness - description: The brightness value to set. selector: number: min: 0 max: 100 unit_of_measurement: "%" start_flow: - name: Start flow - description: Start a custom flow, using transitions from https://yeelight.readthedocs.io/en/stable/yeelight.html#flow-objects target: entity: integration: yeelight domain: light fields: count: - name: Count - description: The number of times to run this flow (0 to run forever). default: 0 selector: number: min: 0 max: 100 action: - name: Action - description: The action to take after the flow stops. default: "recover" selector: select: options: - - label: "Off" - value: "off" - - label: "Recover" - value: "recover" - - label: "Stay" - value: "stay" + - "off" + - "recover" + - "stay" + translation_key: action transitions: - name: Transitions - description: Array of transitions, for desired effect. Examples https://yeelight.readthedocs.io/en/stable/flow.html - example: '[{ "TemperatureTransition": [1900, 1000, 80] }, { "TemperatureTransition": [1900, 1000, 10] }]' + example: + '[{ "TemperatureTransition": [1900, 1000, 80] }, { "TemperatureTransition": + [1900, 1000, 10] }]' selector: object: set_music_mode: - name: Set music mode - description: Enable or disable music_mode target: entity: integration: yeelight domain: light fields: music_mode: - name: Music mode - description: Use true or false to enable / disable music_mode required: true selector: boolean: diff --git a/homeassistant/components/yeelight/strings.json b/homeassistant/components/yeelight/strings.json index 0ecbd134b6af94..18b762057a78bb 100644 --- a/homeassistant/components/yeelight/strings.json +++ b/homeassistant/components/yeelight/strings.json @@ -37,5 +37,138 @@ } } } + }, + "services": { + "set_mode": { + "name": "Set mode", + "description": "Sets a operation mode.", + "fields": { + "mode": { + "name": "Mode", + "description": "Operation mode." + } + } + }, + "set_color_scene": { + "name": "Set color scene", + "description": "Changes the light to the specified RGB color and brightness. If the light is off, it will be turned on.", + "fields": { + "rgb_color": { + "name": "RGB color", + "description": "Color for the light in RGB-format." + }, + "brightness": { + "name": "Brightness", + "description": "The brightness value to set." + } + } + }, + "set_hsv_scene": { + "name": "Set HSV scene", + "description": "Changes the light to the specified HSV color and brightness. If the light is off, it will be turned on.", + "fields": { + "hs_color": { + "name": "Hue/sat color", + "description": "Color for the light in hue/sat format. Hue is 0-359 and Sat is 0-100." + }, + "brightness": { + "name": "Brightness", + "description": "The brightness value to set." + } + } + }, + "set_color_temp_scene": { + "name": "Set color temperature scene", + "description": "Changes the light to the specified color temperature. If the light is off, it will be turned on.", + "fields": { + "kelvin": { + "name": "Kelvin", + "description": "Color temperature for the light in Kelvin." + }, + "brightness": { + "name": "Brightness", + "description": "The brightness value to set." + } + } + }, + "set_color_flow_scene": { + "name": "Set color flow scene", + "description": "Starts a color flow. If the light is off, it will be turned on.", + "fields": { + "count": { + "name": "Count", + "description": "The number of times to run this flow (0 to run forever)." + }, + "action": { + "name": "Action", + "description": "The action to take after the flow stops." + }, + "transitions": { + "name": "Transitions", + "description": "Array of transitions, for desired effect. Examples https://yeelight.readthedocs.io/en/stable/flow.html." + } + } + }, + "set_auto_delay_off_scene": { + "name": "Set auto delay off scene", + "description": "Turns the light on to the specified brightness and sets a timer to turn it back off after the given number of minutes. If the light is off, Set a color scene, if light is off, it will be turned on.", + "fields": { + "minutes": { + "name": "Minutes", + "description": "The time to wait before automatically turning the light off." + }, + "brightness": { + "name": "Brightness", + "description": "The brightness value to set." + } + } + }, + "start_flow": { + "name": "Start flow", + "description": "Start a custom flow, using transitions from https://yeelight.readthedocs.io/en/stable/yeelight.html#flow-objects.", + "fields": { + "count": { + "name": "Count", + "description": "The number of times to run this flow (0 to run forever)." + }, + "action": { + "name": "Action", + "description": "The action to take after the flow stops." + }, + "transitions": { + "name": "Transitions", + "description": "Array of transitions, for desired effect. Examples https://yeelight.readthedocs.io/en/stable/flow.html." + } + } + }, + "set_music_mode": { + "name": "Set music mode", + "description": "Enables or disables music_mode.", + "fields": { + "music_mode": { + "name": "Music mode", + "description": "Use true or false to enable / disable music_mode." + } + } + } + }, + "selector": { + "mode": { + "options": { + "color_flow": "Color Flow", + "hsv": "HSV", + "last": "Last", + "moonlight": "Moonlight", + "normal": "Normal", + "rgb": "RGB" + } + }, + "action": { + "options": { + "off": "Off", + "recover": "Recover", + "stay": "Stay" + } + } } } diff --git a/homeassistant/components/zoneminder/services.yaml b/homeassistant/components/zoneminder/services.yaml index 74ab0cf594585b..30e6672957da20 100644 --- a/homeassistant/components/zoneminder/services.yaml +++ b/homeassistant/components/zoneminder/services.yaml @@ -1,10 +1,6 @@ set_run_state: - name: Set run state - description: Set the ZoneMinder run state fields: name: - name: Name - description: The string name of the ZoneMinder run state to set as active. required: true example: "Home" selector: diff --git a/homeassistant/components/zoneminder/strings.json b/homeassistant/components/zoneminder/strings.json new file mode 100644 index 00000000000000..1e2e41d274107e --- /dev/null +++ b/homeassistant/components/zoneminder/strings.json @@ -0,0 +1,14 @@ +{ + "services": { + "set_run_state": { + "name": "Set run state", + "description": "Sets the ZoneMinder run state.", + "fields": { + "name": { + "name": "Name", + "description": "The string name of the ZoneMinder run state to set as active." + } + } + } + } +} From 4edec696376393976bcd165f10f90249c1b46daf Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 07:37:13 +0200 Subject: [PATCH 070/154] Migrate integration services (T-V) to support translations (#96379) --- homeassistant/components/tado/services.yaml | 18 - homeassistant/components/tado/strings.json | 44 ++ .../components/telegram/services.yaml | 2 - .../components/telegram/strings.json | 8 + .../components/telegram_bot/services.yaml | 327 +--------- .../components/telegram_bot/strings.json | 596 ++++++++++++++++++ homeassistant/components/timer/services.yaml | 12 - homeassistant/components/timer/strings.json | 34 + .../components/todoist/services.yaml | 24 - homeassistant/components/todoist/strings.json | 54 ++ homeassistant/components/toon/services.yaml | 4 - homeassistant/components/toon/strings.json | 12 + .../components/totalconnect/services.yaml | 4 - .../components/totalconnect/strings.json | 10 + homeassistant/components/tplink/services.yaml | 32 - homeassistant/components/tplink/strings.json | 94 +++ .../components/transmission/services.yaml | 26 - .../components/transmission/strings.json | 62 ++ homeassistant/components/unifi/services.yaml | 6 - homeassistant/components/unifi/strings.json | 16 + .../components/unifiprotect/services.yaml | 25 - .../components/unifiprotect/strings.json | 58 ++ homeassistant/components/upb/services.yaml | 38 -- homeassistant/components/upb/strings.json | 88 +++ .../components/utility_meter/services.yaml | 6 - .../components/utility_meter/strings.json | 16 + homeassistant/components/vallox/services.yaml | 12 - homeassistant/components/vallox/strings.json | 32 + homeassistant/components/velbus/services.yaml | 30 - homeassistant/components/velbus/strings.json | 54 ++ homeassistant/components/velux/services.yaml | 2 - homeassistant/components/velux/strings.json | 8 + .../components/verisure/services.yaml | 6 - .../components/verisure/strings.json | 14 + homeassistant/components/vesync/services.yaml | 2 - homeassistant/components/vesync/strings.json | 6 + homeassistant/components/vicare/services.yaml | 4 - homeassistant/components/vicare/strings.json | 12 + homeassistant/components/vizio/services.yaml | 12 - homeassistant/components/vizio/strings.json | 20 + 40 files changed, 1272 insertions(+), 558 deletions(-) create mode 100644 homeassistant/components/telegram/strings.json create mode 100644 homeassistant/components/telegram_bot/strings.json create mode 100644 homeassistant/components/todoist/strings.json create mode 100644 homeassistant/components/velux/strings.json diff --git a/homeassistant/components/tado/services.yaml b/homeassistant/components/tado/services.yaml index 211ae4cd1ff79a..0f66798f864c5e 100644 --- a/homeassistant/components/tado/services.yaml +++ b/homeassistant/components/tado/services.yaml @@ -1,14 +1,10 @@ set_climate_timer: - name: Set climate timer - description: Turn on climate entities for a set time. target: entity: integration: tado domain: climate fields: temperature: - name: Temperature - description: Temperature to set climate entity to required: true selector: number: @@ -17,15 +13,11 @@ set_climate_timer: step: 0.5 unit_of_measurement: "°" time_period: - name: Time period - description: Choose this or Overlay. Set the time period for the change if you want to be specific. Alternatively use Overlay required: false example: "01:30:00" selector: text: requested_overlay: - name: Overlay - description: Choose this or Time Period. Allows you to choose an overlay. MANUAL:=Overlay until user removes; NEXT_TIME_BLOCK:=Overlay until next timeblock; TADO_DEFAULT:=Overlay based on tado app setting required: false example: "MANUAL" selector: @@ -36,24 +28,18 @@ set_climate_timer: - "TADO_DEFAULT" set_water_heater_timer: - name: Set water heater timer - description: Turn on water heater for a set time. target: entity: integration: tado domain: water_heater fields: time_period: - name: Time period - description: Set the time period for the boost. required: true example: "01:30:00" default: "01:00:00" selector: text: temperature: - name: Temperature - description: Temperature to set heater to selector: number: min: 0 @@ -62,16 +48,12 @@ set_water_heater_timer: unit_of_measurement: "°" set_climate_temperature_offset: - name: Set climate temperature offset - description: Set the temperature offset of climate entities target: entity: integration: tado domain: climate fields: offset: - name: Offset - description: Offset you would like (depending on your device). default: 0 selector: number: diff --git a/homeassistant/components/tado/strings.json b/homeassistant/components/tado/strings.json index 3decfe3cd0c925..70ff38b10be719 100644 --- a/homeassistant/components/tado/strings.json +++ b/homeassistant/components/tado/strings.json @@ -42,5 +42,49 @@ } } } + }, + "services": { + "set_climate_timer": { + "name": "Set climate timer", + "description": "Turns on climate entities for a set time.", + "fields": { + "temperature": { + "name": "Temperature", + "description": "Temperature to set climate entity to." + }, + "time_period": { + "name": "Time period", + "description": "Choose this or Overlay. Set the time period for the change if you want to be specific. Alternatively use Overlay." + }, + "requested_overlay": { + "name": "Overlay", + "description": "Choose this or Time Period. Allows you to choose an overlay. MANUAL:=Overlay until user removes; NEXT_TIME_BLOCK:=Overlay until next timeblock; TADO_DEFAULT:=Overlay based on tado app setting." + } + } + }, + "set_water_heater_timer": { + "name": "Set water heater timer", + "description": "Turns on water heater for a set time.", + "fields": { + "time_period": { + "name": "Time period", + "description": "Set the time period for the boost." + }, + "temperature": { + "name": "Temperature", + "description": "Temperature to set heater to." + } + } + }, + "set_climate_temperature_offset": { + "name": "Set climate temperature offset", + "description": "Sets the temperature offset of climate entities.", + "fields": { + "offset": { + "name": "Offset", + "description": "Offset you would like (depending on your device)." + } + } + } } } diff --git a/homeassistant/components/telegram/services.yaml b/homeassistant/components/telegram/services.yaml index bbdd82768f596e..c983a105c93977 100644 --- a/homeassistant/components/telegram/services.yaml +++ b/homeassistant/components/telegram/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload telegram notify services. diff --git a/homeassistant/components/telegram/strings.json b/homeassistant/components/telegram/strings.json new file mode 100644 index 00000000000000..9e09a3904cd702 --- /dev/null +++ b/homeassistant/components/telegram/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "reload": { + "name": "Reload", + "description": "Reloads telegram notify services." + } + } +} diff --git a/homeassistant/components/telegram_bot/services.yaml b/homeassistant/components/telegram_bot/services.yaml index 31876bd542d912..cdb50d55943ba4 100644 --- a/homeassistant/components/telegram_bot/services.yaml +++ b/homeassistant/components/telegram_bot/services.yaml @@ -1,31 +1,21 @@ # Describes the format for available Telegram bot services send_message: - name: Send message - description: Send a notification. fields: message: - name: Message - description: Message body of the notification. required: true example: The garage door has been open for 10 minutes. selector: text: title: - name: Title - description: Optional title for your notification. Will be composed as '%title\n%message' example: "Your Garage Door Friend" selector: text: target: - name: Target - description: An array of pre-authorized chat_ids to send the notification to. If not present, first allowed chat_id is the default. example: "[12345, 67890] or 12345" selector: object: parse_mode: - name: Parse mode - description: "Parser for the message text." selector: select: options: @@ -33,18 +23,12 @@ send_message: - "markdown" - "markdown2" disable_notification: - name: Disable notification - description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. selector: boolean: disable_web_page_preview: - name: Disable web page preview - description: Disables link previews for links in the message. selector: boolean: timeout: - name: Timeout - description: Timeout for send message. Will help with timeout errors (poor internet connection, etc)s selector: number: min: 1 @@ -52,61 +36,44 @@ send_message: unit_of_measurement: seconds keyboard: - name: Keyboard - description: List of rows of commands, comma-separated, to make a custom keyboard. Empty list clears a previously set keyboard. example: '["/command1, /command2", "/command3"]' selector: object: inline_keyboard: - name: Inline keyboard - description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. - example: '["/button1, /button2", "/button3"] or ["Text button1:/button1, Text button2:/button2", "Text button3:/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + example: + '["/button1, /button2", "/button3"] or ["Text button1:/button1, Text + button2:/button2", "Text button3:/button3"] or [[["Text button1", "/button1"], + ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' selector: object: message_tag: - name: Message tag - description: "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}" example: "msg_to_edit" selector: text: send_photo: - name: Send photo - description: Send a photo. fields: url: - name: URL - description: Remote path to an image. example: "http://example.org/path/to/the/image.png" selector: text: file: - name: File - description: Local path to an image. example: "/path/to/the/image.png" selector: text: caption: - name: Caption - description: The title of the image. example: "My image" selector: text: username: - name: Username - description: Username for a URL which require HTTP authentication. example: myuser selector: text: password: - name: Password - description: Password (or bearer token) for a URL which require HTTP authentication. example: myuser_pwd selector: text: authentication: - name: Authentication method - description: Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`. default: digest selector: select: @@ -114,14 +81,10 @@ send_photo: - "digest" - "bearer_token" target: - name: Target - description: An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default. example: "[12345, 67890] or 12345" selector: object: parse_mode: - name: Parse mode - description: "Parser for the message text." selector: select: options: @@ -129,79 +92,55 @@ send_photo: - "markdown" - "markdown2" disable_notification: - name: Disable notification - description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. selector: boolean: verify_ssl: - name: Verify SSL - description: Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server. selector: boolean: timeout: - name: Timeout - description: Timeout for send photo. Will help with timeout errors (poor internet connection, etc) selector: number: min: 1 max: 3600 unit_of_measurement: seconds keyboard: - name: Keyboard - description: List of rows of commands, comma-separated, to make a custom keyboard. example: '["/command1, /command2", "/command3"]' selector: object: inline_keyboard: - name: Inline keyboard - description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. - example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + example: + '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], + ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' selector: object: message_tag: - name: Message tag - description: "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}" example: "msg_to_edit" selector: text: send_sticker: - name: Send sticker - description: Send a sticker. fields: url: - name: URL - description: Remote path to a static .webp or animated .tgs sticker. example: "http://example.org/path/to/the/sticker.webp" selector: text: file: - name: File - description: Local path to a static .webp or animated .tgs sticker. example: "/path/to/the/sticker.webp" selector: text: sticker_id: - name: Sticker ID - description: ID of a sticker that exists on telegram servers example: CAACAgIAAxkBAAEDDldhZD-hqWclr6krLq-FWSfCrGNmOQAC9gAD9HsZAAFeYY-ltPYnrCEE selector: text: username: - name: Username - description: Username for a URL which require HTTP authentication. example: myuser selector: text: password: - name: Password - description: Password (or bearer token) for a URL which require HTTP authentication. example: myuser_pwd selector: text: authentication: - name: Authentication method - description: Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`. default: digest selector: select: @@ -209,85 +148,59 @@ send_sticker: - "digest" - "bearer_token" target: - name: Target - description: An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default. example: "[12345, 67890] or 12345" selector: object: disable_notification: - name: Disable notification - description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. selector: boolean: verify_ssl: - name: Verify SSL - description: Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server. selector: boolean: timeout: - name: Timeout - description: Timeout for send sticker. Will help with timeout errors (poor internet connection, etc) selector: number: min: 1 max: 3600 unit_of_measurement: seconds keyboard: - name: Keyboard - description: List of rows of commands, comma-separated, to make a custom keyboard. example: '["/command1, /command2", "/command3"]' selector: object: inline_keyboard: - name: Inline keyboard - description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. - example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + example: + '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], + ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' selector: object: message_tag: - name: Message tag - description: "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}" example: "msg_to_edit" selector: text: send_animation: - name: Send animation - description: Send an anmiation. fields: url: - name: URL - description: Remote path to a GIF or H.264/MPEG-4 AVC video without sound. example: "http://example.org/path/to/the/animation.gif" selector: text: file: - name: File - description: Local path to a GIF or H.264/MPEG-4 AVC video without sound. example: "/path/to/the/animation.gif" selector: text: caption: - name: Caption - description: The title of the animation. example: "My animation" selector: text: username: - name: Username - description: Username for a URL which require HTTP authentication. example: myuser selector: text: password: - name: Password - description: Password (or bearer token) for a URL which require HTTP authentication. example: myuser_pwd selector: text: authentication: - name: Authentication method - description: Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`. default: digest selector: select: @@ -295,14 +208,10 @@ send_animation: - "digest" - "bearer_token" target: - name: Target - description: An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default. example: "[12345, 67890] or 12345" selector: object: parse_mode: - name: Parse Mode - description: "Parser for the message text." selector: select: options: @@ -310,73 +219,51 @@ send_animation: - "markdown" - "markdown2" disable_notification: - name: Disable notification - description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. selector: boolean: verify_ssl: - name: Verify SSL - description: Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server. selector: boolean: timeout: - name: Timeout - description: Timeout for send sticker. Will help with timeout errors (poor internet connection, etc) selector: number: min: 1 max: 3600 unit_of_measurement: seconds keyboard: - name: Keyboard - description: List of rows of commands, comma-separated, to make a custom keyboard. example: '["/command1, /command2", "/command3"]' selector: object: inline_keyboard: - name: Inline keyboard - description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. - example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + example: + '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], + ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' selector: object: send_video: - name: Send video - description: Send a video. fields: url: - name: URL - description: Remote path to a video. example: "http://example.org/path/to/the/video.mp4" selector: text: file: - name: File - description: Local path to a video. example: "/path/to/the/video.mp4" selector: text: caption: - name: Caption - description: The title of the video. example: "My video" selector: text: username: - name: Username - description: Username for a URL which require HTTP authentication. example: myuser selector: text: password: - name: Password - description: Password (or bearer token) for a URL which require HTTP authentication. example: myuser_pwd selector: text: authentication: - name: Authentication method - description: Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`. default: digest selector: select: @@ -384,14 +271,10 @@ send_video: - "digest" - "bearer_token" target: - name: Target - description: An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default. example: "[12345, 67890] or 12345" selector: object: parse_mode: - name: Parse mode - description: "Parser for the message text." selector: select: options: @@ -399,79 +282,55 @@ send_video: - "markdown" - "markdown2" disable_notification: - name: Disable notification - description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. selector: boolean: verify_ssl: - name: Verify SSL - description: Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server. selector: boolean: timeout: - name: Timeout - description: Timeout for send video. Will help with timeout errors (poor internet connection, etc) selector: number: min: 1 max: 3600 unit_of_measurement: seconds keyboard: - name: Keyboard - description: List of rows of commands, comma-separated, to make a custom keyboard. example: '["/command1, /command2", "/command3"]' selector: object: inline_keyboard: - name: Inline keyboard - description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. - example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + example: + '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], + ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' selector: object: message_tag: - name: Message tag - description: "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}" example: "msg_to_edit" selector: text: send_voice: - name: Send voice - description: Send a voice message. fields: url: - name: URL - description: Remote path to a voice message. example: "http://example.org/path/to/the/voice.opus" selector: text: file: - name: File - description: Local path to a voice message. example: "/path/to/the/voice.opus" selector: text: caption: - name: Caption - description: The title of the voice message. example: "My microphone recording" selector: text: username: - name: Username - description: Username for a URL which require HTTP authentication. example: myuser selector: text: password: - name: Password - description: Password (or bearer token) for a URL which require HTTP authentication. example: myuser_pwd selector: text: authentication: - name: Authentication method - description: Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`. default: digest selector: select: @@ -479,85 +338,59 @@ send_voice: - "digest" - "bearer_token" target: - name: Target - description: An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default. example: "[12345, 67890] or 12345" selector: object: disable_notification: - name: Disable notification - description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. selector: boolean: verify_ssl: - name: Verify SSL - description: Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server. selector: boolean: timeout: - name: Timeout - description: Timeout for send voice. Will help with timeout errors (poor internet connection, etc) selector: number: min: 1 max: 3600 unit_of_measurement: seconds keyboard: - name: Keyboard - description: List of rows of commands, comma-separated, to make a custom keyboard. example: '["/command1, /command2", "/command3"]' selector: object: inline_keyboard: - name: Inline keyboard - description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. - example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + example: + '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], + ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' selector: object: message_tag: - name: Message tag - description: "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}" example: "msg_to_edit" selector: text: send_document: - name: Send document - description: Send a document. fields: url: - name: URL - description: Remote path to a document. example: "http://example.org/path/to/the/document.odf" selector: text: file: - name: File - description: Local path to a document. example: "/tmp/whatever.odf" selector: text: caption: - name: Caption - description: The title of the document. example: Document Title xy selector: text: username: - name: Username - description: Username for a URL which require HTTP authentication. example: myuser selector: text: password: - name: Password - description: Password (or bearer token) for a URL which require HTTP authentication. example: myuser_pwd selector: text: authentication: - name: Authentication method - description: Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`. default: digest selector: select: @@ -565,14 +398,10 @@ send_document: - "digest" - "bearer_token" target: - name: Target - description: An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default. example: "[12345, 67890] or 12345" selector: object: parse_mode: - name: Parse mode - description: "Parser for the message text." selector: select: options: @@ -580,49 +409,35 @@ send_document: - "markdown" - "markdown2" disable_notification: - name: Disable notification - description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. selector: boolean: verify_ssl: - name: Verify SSL - description: Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server. selector: boolean: timeout: - name: Timeout - description: Timeout for send document. Will help with timeout errors (poor internet connection, etc) selector: number: min: 1 max: 3600 unit_of_measurement: seconds keyboard: - name: Keyboard - description: List of rows of commands, comma-separated, to make a custom keyboard. example: '["/command1, /command2", "/command3"]' selector: object: inline_keyboard: - name: Inline keyboard - description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. - example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + example: + '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], + ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' selector: object: message_tag: - name: Message tag - description: "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}" example: "msg_to_edit" selector: text: send_location: - name: Send location - description: Send a location. fields: latitude: - name: Latitude - description: The latitude to send. required: true selector: number: @@ -631,8 +446,6 @@ send_location: step: 0.001 unit_of_measurement: "°" longitude: - name: Longitude - description: The longitude to send. required: true selector: number: @@ -641,91 +454,63 @@ send_location: step: 0.001 unit_of_measurement: "°" target: - name: Target - description: An array of pre-authorized chat_ids to send the location to. If not present, first allowed chat_id is the default. example: "[12345, 67890] or 12345" selector: object: disable_notification: - name: Disable notification - description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. selector: boolean: timeout: - name: Timeout - description: Timeout for send photo. Will help with timeout errors (poor internet connection, etc) selector: number: min: 1 max: 3600 unit_of_measurement: seconds keyboard: - name: Keyboard - description: List of rows of commands, comma-separated, to make a custom keyboard. example: '["/command1, /command2", "/command3"]' selector: object: inline_keyboard: - name: Inline keyboard - description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. - example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + example: + '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], + ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' selector: object: message_tag: - name: Message tag - description: "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}" example: "msg_to_edit" selector: text: send_poll: - name: Send poll - description: Send a poll. fields: target: - name: Target - description: An array of pre-authorized chat_ids to send the location to. If not present, first allowed chat_id is the default. example: "[12345, 67890] or 12345" selector: object: question: - name: Question - description: Poll question, 1-300 characters required: true selector: text: options: - name: Options - description: List of answer options, 2-10 strings 1-100 characters each required: true selector: object: is_anonymous: - name: Is Anonymous - description: If the poll needs to be anonymous, defaults to True selector: boolean: allows_multiple_answers: - name: Allow Multiple Answers - description: If the poll allows multiple answers, defaults to False selector: boolean: open_period: - name: Open Period - description: Amount of time in seconds the poll will be active after creation, 5-600. selector: number: min: 5 max: 600 unit_of_measurement: seconds disable_notification: - name: Disable notification - description: Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound. selector: boolean: timeout: - name: Timeout - description: Timeout for send poll. Will help with timeout errors (poor internet connection, etc) selector: number: min: 1 @@ -733,38 +518,26 @@ send_poll: unit_of_measurement: seconds edit_message: - name: Edit message - description: Edit a previously sent message. fields: message_id: - name: Message ID - description: id of the message to edit. required: true example: "{{ trigger.event.data.message.message_id }}" selector: text: chat_id: - name: Chat ID - description: The chat_id where to edit the message. required: true example: 12345 selector: text: message: - name: Message - description: Message body of the notification. example: The garage door has been open for 10 minutes. selector: text: title: - name: Title - description: Optional title for your notification. Will be composed as '%title\n%message' example: "Your Garage Door Friend" selector: text: parse_mode: - name: Parse mode - description: "Parser for the message text." selector: select: options: @@ -772,102 +545,76 @@ edit_message: - "markdown" - "markdown2" disable_web_page_preview: - name: Disable web page preview - description: Disables link previews for links in the message. selector: boolean: inline_keyboard: - name: Inline keyboard - description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. - example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + example: + '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], + ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' selector: object: edit_caption: - name: Edit caption - description: Edit the caption of a previously sent message. fields: message_id: - name: Message ID - description: id of the message to edit. required: true example: "{{ trigger.event.data.message.message_id }}" selector: text: chat_id: - name: Chat ID - description: The chat_id where to edit the caption. required: true example: 12345 selector: text: caption: - name: Caption - description: Message body of the notification. required: true example: The garage door has been open for 10 minutes. selector: text: inline_keyboard: - name: Inline keyboard - description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. - example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + example: + '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], + ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' selector: object: edit_replymarkup: - name: Edit reply markup - description: Edit the inline keyboard of a previously sent message. fields: message_id: - name: Message ID - description: id of the message to edit. required: true example: "{{ trigger.event.data.message.message_id }}" selector: text: chat_id: - name: Chat ID - description: The chat_id where to edit the reply_markup. required: true example: 12345 selector: text: inline_keyboard: - name: Inline keyboard - description: List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data. required: true - example: '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' + example: + '["/button1, /button2", "/button3"] or [[["Text button1", "/button1"], + ["Text button2", "/button2"]], [["Text button3", "/button3"]]]' selector: object: answer_callback_query: - name: Answer callback query - description: Respond to a callback query originated by clicking on an online keyboard button. The answer will be displayed to the user as a notification at the top of the chat screen or as an alert. fields: message: - name: Message - description: Unformatted text message body of the notification. required: true example: "OK, I'm listening" selector: text: callback_query_id: - name: Callback query ID - description: Unique id of the callback response. required: true example: "{{ trigger.event.data.id }}" selector: text: show_alert: - name: Show alert - description: Show a permanent notification. required: true selector: boolean: timeout: - name: Timeout - description: Timeout for sending the answer. Will help with timeout errors (poor internet connection, etc) selector: number: min: 1 @@ -875,19 +622,13 @@ answer_callback_query: unit_of_measurement: seconds delete_message: - name: Delete message - description: Delete a previously sent message. fields: message_id: - name: Message ID - description: id of the message to delete. required: true example: "{{ trigger.event.data.message.message_id }}" selector: text: chat_id: - name: Chat ID - description: The chat_id where to delete the message. required: true example: 12345 selector: diff --git a/homeassistant/components/telegram_bot/strings.json b/homeassistant/components/telegram_bot/strings.json new file mode 100644 index 00000000000000..8104fdd285e369 --- /dev/null +++ b/homeassistant/components/telegram_bot/strings.json @@ -0,0 +1,596 @@ +{ + "services": { + "send_message": { + "name": "Send message", + "description": "Sends a notification.", + "fields": { + "message": { + "name": "Message", + "description": "Message body of the notification." + }, + "title": { + "name": "Title", + "description": "Optional title for your notification. Will be composed as '%title\\n%message'." + }, + "target": { + "name": "Target", + "description": "An array of pre-authorized chat_ids to send the notification to. If not present, first allowed chat_id is the default." + }, + "parse_mode": { + "name": "Parse mode", + "description": "Parser for the message text." + }, + "disable_notification": { + "name": "Disable notification", + "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + }, + "disable_web_page_preview": { + "name": "Disable web page preview", + "description": "Disables link previews for links in the message." + }, + "timeout": { + "name": "Timeout", + "description": "Timeout for send message. Will help with timeout errors (poor internet connection, etc)s." + }, + "keyboard": { + "name": "Keyboard", + "description": "List of rows of commands, comma-separated, to make a custom keyboard. Empty list clears a previously set keyboard." + }, + "inline_keyboard": { + "name": "Inline keyboard", + "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + }, + "message_tag": { + "name": "Message tag", + "description": "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}." + } + } + }, + "send_photo": { + "name": "Send photo", + "description": "Sends a photo.", + "fields": { + "url": { + "name": "URL", + "description": "Remote path to an image." + }, + "file": { + "name": "File", + "description": "Local path to an image." + }, + "caption": { + "name": "Caption", + "description": "The title of the image." + }, + "username": { + "name": "Username", + "description": "Username for a URL which require HTTP authentication." + }, + "password": { + "name": "Password", + "description": "Password (or bearer token) for a URL which require HTTP authentication." + }, + "authentication": { + "name": "Authentication method", + "description": "Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`." + }, + "target": { + "name": "Target", + "description": "An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default." + }, + "parse_mode": { + "name": "Parse mode", + "description": "Parser for the message text." + }, + "disable_notification": { + "name": "Disable notification", + "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + }, + "verify_ssl": { + "name": "Verify SSL", + "description": "Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server." + }, + "timeout": { + "name": "Timeout", + "description": "Timeout for send photo. Will help with timeout errors (poor internet connection, etc)." + }, + "keyboard": { + "name": "Keyboard", + "description": "List of rows of commands, comma-separated, to make a custom keyboard." + }, + "inline_keyboard": { + "name": "Inline keyboard", + "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + }, + "message_tag": { + "name": "Message tag", + "description": "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}." + } + } + }, + "send_sticker": { + "name": "Send sticker", + "description": "Sends a sticker.", + "fields": { + "url": { + "name": "URL", + "description": "Remote path to a static .webp or animated .tgs sticker." + }, + "file": { + "name": "File", + "description": "Local path to a static .webp or animated .tgs sticker." + }, + "sticker_id": { + "name": "Sticker ID", + "description": "ID of a sticker that exists on telegram servers." + }, + "username": { + "name": "Username", + "description": "Username for a URL which require HTTP authentication." + }, + "password": { + "name": "Password", + "description": "Password (or bearer token) for a URL which require HTTP authentication." + }, + "authentication": { + "name": "Authentication method", + "description": "Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`." + }, + "target": { + "name": "Target", + "description": "An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default." + }, + "disable_notification": { + "name": "Disable notification", + "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + }, + "verify_ssl": { + "name": "Verify SSL", + "description": "Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server." + }, + "timeout": { + "name": "Timeout", + "description": "Timeout for send sticker. Will help with timeout errors (poor internet connection, etc)." + }, + "keyboard": { + "name": "Keyboard", + "description": "List of rows of commands, comma-separated, to make a custom keyboard." + }, + "inline_keyboard": { + "name": "Inline keyboard", + "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + }, + "message_tag": { + "name": "Message tag", + "description": "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}." + } + } + }, + "send_animation": { + "name": "Send animation", + "description": "Sends an anmiation.", + "fields": { + "url": { + "name": "URL", + "description": "Remote path to a GIF or H.264/MPEG-4 AVC video without sound." + }, + "file": { + "name": "File", + "description": "Local path to a GIF or H.264/MPEG-4 AVC video without sound." + }, + "caption": { + "name": "Caption", + "description": "The title of the animation." + }, + "username": { + "name": "Username", + "description": "Username for a URL which require HTTP authentication." + }, + "password": { + "name": "Password", + "description": "Password (or bearer token) for a URL which require HTTP authentication." + }, + "authentication": { + "name": "Authentication method", + "description": "Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`." + }, + "target": { + "name": "Target", + "description": "An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default." + }, + "parse_mode": { + "name": "Parse Mode", + "description": "Parser for the message text." + }, + "disable_notification": { + "name": "Disable notification", + "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + }, + "verify_ssl": { + "name": "Verify SSL", + "description": "Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server." + }, + "timeout": { + "name": "Timeout", + "description": "Timeout for send sticker. Will help with timeout errors (poor internet connection, etc)." + }, + "keyboard": { + "name": "Keyboard", + "description": "List of rows of commands, comma-separated, to make a custom keyboard." + }, + "inline_keyboard": { + "name": "Inline keyboard", + "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + } + } + }, + "send_video": { + "name": "Send video", + "description": "Sends a video.", + "fields": { + "url": { + "name": "URL", + "description": "Remote path to a video." + }, + "file": { + "name": "File", + "description": "Local path to a video." + }, + "caption": { + "name": "Caption", + "description": "The title of the video." + }, + "username": { + "name": "Username", + "description": "Username for a URL which require HTTP authentication." + }, + "password": { + "name": "Password", + "description": "Password (or bearer token) for a URL which require HTTP authentication." + }, + "authentication": { + "name": "Authentication method", + "description": "Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`." + }, + "target": { + "name": "Target", + "description": "An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default." + }, + "parse_mode": { + "name": "Parse mode", + "description": "Parser for the message text." + }, + "disable_notification": { + "name": "Disable notification", + "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + }, + "verify_ssl": { + "name": "Verify SSL", + "description": "Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server." + }, + "timeout": { + "name": "Timeout", + "description": "Timeout for send video. Will help with timeout errors (poor internet connection, etc)." + }, + "keyboard": { + "name": "Keyboard", + "description": "List of rows of commands, comma-separated, to make a custom keyboard." + }, + "inline_keyboard": { + "name": "Inline keyboard", + "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + }, + "message_tag": { + "name": "Message tag", + "description": "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}." + } + } + }, + "send_voice": { + "name": "Send voice", + "description": "Sends a voice message.", + "fields": { + "url": { + "name": "URL", + "description": "Remote path to a voice message." + }, + "file": { + "name": "File", + "description": "Local path to a voice message." + }, + "caption": { + "name": "Caption", + "description": "The title of the voice message." + }, + "username": { + "name": "Username", + "description": "Username for a URL which require HTTP authentication." + }, + "password": { + "name": "Password", + "description": "Password (or bearer token) for a URL which require HTTP authentication." + }, + "authentication": { + "name": "Authentication method", + "description": "Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`." + }, + "target": { + "name": "Target", + "description": "An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default." + }, + "disable_notification": { + "name": "Disable notification", + "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + }, + "verify_ssl": { + "name": "Verify SSL", + "description": "Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server." + }, + "timeout": { + "name": "Timeout", + "description": "Timeout for send voice. Will help with timeout errors (poor internet connection, etc)." + }, + "keyboard": { + "name": "Keyboard", + "description": "List of rows of commands, comma-separated, to make a custom keyboard." + }, + "inline_keyboard": { + "name": "Inline keyboard", + "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + }, + "message_tag": { + "name": "Message tag", + "description": "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}." + } + } + }, + "send_document": { + "name": "Send document", + "description": "Sends a document.", + "fields": { + "url": { + "name": "URL", + "description": "Remote path to a document." + }, + "file": { + "name": "File", + "description": "Local path to a document." + }, + "caption": { + "name": "Caption", + "description": "The title of the document." + }, + "username": { + "name": "Username", + "description": "Username for a URL which require HTTP authentication." + }, + "password": { + "name": "Password", + "description": "Password (or bearer token) for a URL which require HTTP authentication." + }, + "authentication": { + "name": "Authentication method", + "description": "Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`." + }, + "target": { + "name": "Target", + "description": "An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default." + }, + "parse_mode": { + "name": "Parse mode", + "description": "Parser for the message text." + }, + "disable_notification": { + "name": "Disable notification", + "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + }, + "verify_ssl": { + "name": "Verify SSL", + "description": "Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server." + }, + "timeout": { + "name": "Timeout", + "description": "Timeout for send document. Will help with timeout errors (poor internet connection, etc)." + }, + "keyboard": { + "name": "Keyboard", + "description": "List of rows of commands, comma-separated, to make a custom keyboard." + }, + "inline_keyboard": { + "name": "Inline keyboard", + "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + }, + "message_tag": { + "name": "Message tag", + "description": "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}." + } + } + }, + "send_location": { + "name": "Send location", + "description": "Sends a location.", + "fields": { + "latitude": { + "name": "Latitude", + "description": "The latitude to send." + }, + "longitude": { + "name": "Longitude", + "description": "The longitude to send." + }, + "target": { + "name": "Target", + "description": "An array of pre-authorized chat_ids to send the location to. If not present, first allowed chat_id is the default." + }, + "disable_notification": { + "name": "Disable notification", + "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + }, + "timeout": { + "name": "Timeout", + "description": "Timeout for send photo. Will help with timeout errors (poor internet connection, etc)." + }, + "keyboard": { + "name": "Keyboard", + "description": "List of rows of commands, comma-separated, to make a custom keyboard." + }, + "inline_keyboard": { + "name": "Inline keyboard", + "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + }, + "message_tag": { + "name": "Message tag", + "description": "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}." + } + } + }, + "send_poll": { + "name": "Send poll", + "description": "Sends a poll.", + "fields": { + "target": { + "name": "Target", + "description": "An array of pre-authorized chat_ids to send the location to. If not present, first allowed chat_id is the default." + }, + "question": { + "name": "Question", + "description": "Poll question, 1-300 characters." + }, + "options": { + "name": "Options", + "description": "List of answer options, 2-10 strings 1-100 characters each." + }, + "is_anonymous": { + "name": "Is anonymous", + "description": "If the poll needs to be anonymous, defaults to True." + }, + "allows_multiple_answers": { + "name": "Allow multiple answers", + "description": "If the poll allows multiple answers, defaults to False." + }, + "open_period": { + "name": "Open period", + "description": "Amount of time in seconds the poll will be active after creation, 5-600." + }, + "disable_notification": { + "name": "Disable notification", + "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + }, + "timeout": { + "name": "Timeout", + "description": "Timeout for send poll. Will help with timeout errors (poor internet connection, etc)." + } + } + }, + "edit_message": { + "name": "Edit message", + "description": "Edits a previously sent message.", + "fields": { + "message_id": { + "name": "Message ID", + "description": "Id of the message to edit." + }, + "chat_id": { + "name": "Chat ID", + "description": "The chat_id where to edit the message." + }, + "message": { + "name": "Message", + "description": "Message body of the notification." + }, + "title": { + "name": "Title", + "description": "Optional title for your notification. Will be composed as '%title\\n%message'." + }, + "parse_mode": { + "name": "Parse mode", + "description": "Parser for the message text." + }, + "disable_web_page_preview": { + "name": "Disable web page preview", + "description": "Disables link previews for links in the message." + }, + "inline_keyboard": { + "name": "Inline keyboard", + "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + } + } + }, + "edit_caption": { + "name": "Edit caption", + "description": "Edits the caption of a previously sent message.", + "fields": { + "message_id": { + "name": "Message ID", + "description": "Id of the message to edit." + }, + "chat_id": { + "name": "Chat ID", + "description": "The chat_id where to edit the caption." + }, + "caption": { + "name": "Caption", + "description": "Message body of the notification." + }, + "inline_keyboard": { + "name": "Inline keyboard", + "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + } + } + }, + "edit_replymarkup": { + "name": "Edit reply markup", + "description": "Edit the inline keyboard of a previously sent message.", + "fields": { + "message_id": { + "name": "Message ID", + "description": "Id of the message to edit." + }, + "chat_id": { + "name": "Chat ID", + "description": "The chat_id where to edit the reply_markup." + }, + "inline_keyboard": { + "name": "Inline keyboard", + "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + } + } + }, + "answer_callback_query": { + "name": "Answer callback query", + "description": "Responds to a callback query originated by clicking on an online keyboard button. The answer will be displayed to the user as a notification at the top of the chat screen or as an alert.", + "fields": { + "message": { + "name": "Message", + "description": "Unformatted text message body of the notification." + }, + "callback_query_id": { + "name": "Callback query ID", + "description": "Unique id of the callback response." + }, + "show_alert": { + "name": "Show alert", + "description": "Show a permanent notification." + }, + "timeout": { + "name": "Timeout", + "description": "Timeout for sending the answer. Will help with timeout errors (poor internet connection, etc)." + } + } + }, + "delete_message": { + "name": "Delete message", + "description": "Deletes a previously sent message.", + "fields": { + "message_id": { + "name": "Message ID", + "description": "Id of the message to delete." + }, + "chat_id": { + "name": "Chat ID", + "description": "The chat_id where to delete the message." + } + } + } + } +} diff --git a/homeassistant/components/timer/services.yaml b/homeassistant/components/timer/services.yaml index 68caa44a69907f..74eeae22b23051 100644 --- a/homeassistant/components/timer/services.yaml +++ b/homeassistant/components/timer/services.yaml @@ -1,48 +1,36 @@ # Describes the format for available timer services start: - name: Start - description: Start a timer target: entity: domain: timer fields: duration: - description: Duration the timer requires to finish. [optional] example: "00:01:00 or 60" selector: text: pause: - name: Pause - description: Pause a timer. target: entity: domain: timer cancel: - name: Cancel - description: Cancel a timer. target: entity: domain: timer finish: - name: Finish - description: Finish a timer. target: entity: domain: timer change: - name: Change - description: Change a timer target: entity: domain: timer fields: duration: - description: Duration to add or subtract to the running timer default: 0 required: true example: "00:01:00, 60 or -60" diff --git a/homeassistant/components/timer/strings.json b/homeassistant/components/timer/strings.json index 217de09a534ced..e21f0d2ca82484 100644 --- a/homeassistant/components/timer/strings.json +++ b/homeassistant/components/timer/strings.json @@ -29,5 +29,39 @@ } } } + }, + "services": { + "start": { + "name": "Start", + "description": "Starts a timer.", + "fields": { + "duration": { + "name": "Duration", + "description": "Duration the timer requires to finish. [optional]." + } + } + }, + "pause": { + "name": "Pause", + "description": "Pauses a timer." + }, + "cancel": { + "name": "Cancel", + "description": "Cancels a timer." + }, + "finish": { + "name": "Finish", + "description": "Finishes a timer." + }, + "change": { + "name": "Change", + "description": "Changes a timer.", + "fields": { + "duration": { + "name": "Duration", + "description": "Duration to add or subtract to the running timer." + } + } + } } } diff --git a/homeassistant/components/todoist/services.yaml b/homeassistant/components/todoist/services.yaml index 3cab4d2bf673b7..9593b6bb6a40ed 100644 --- a/homeassistant/components/todoist/services.yaml +++ b/homeassistant/components/todoist/services.yaml @@ -1,49 +1,33 @@ new_task: - name: New task - description: Create a new task and add it to a project. fields: content: - name: Content - description: The name of the task. required: true example: Pick up the mail. selector: text: project: - name: Project - description: The name of the project this task should belong to. example: Errands default: Inbox selector: text: labels: - name: Labels - description: Any labels that you want to apply to this task, separated by a comma. example: Chores,Delivieries selector: text: assignee: - name: Assignee - description: A members username of a shared project to assign this task to. example: username selector: text: priority: - name: Priority - description: The priority of this task, from 1 (normal) to 4 (urgent). selector: number: min: 1 max: 4 due_date_string: - name: Due date string - description: The day this task is due, in natural language. example: Tomorrow selector: text: due_date_lang: - name: Due data language - description: The language of due_date_string. selector: select: options: @@ -62,20 +46,14 @@ new_task: - "sv" - "zh" due_date: - name: Due date - description: The time this task is due, in format YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS, in UTC timezone. example: "2019-10-22" selector: text: reminder_date_string: - name: Reminder date string - description: When should user be reminded of this task, in natural language. example: Tomorrow selector: text: reminder_date_lang: - name: Reminder data language - description: The language of reminder_date_string. selector: select: options: @@ -94,8 +72,6 @@ new_task: - "sv" - "zh" reminder_date: - name: Reminder date - description: When should user be reminded of this task, in format YYYY-MM-DDTHH:MM:SS, in UTC timezone. example: "2019-10-22T10:30:00" selector: text: diff --git a/homeassistant/components/todoist/strings.json b/homeassistant/components/todoist/strings.json new file mode 100644 index 00000000000000..1ed092e5cf6e11 --- /dev/null +++ b/homeassistant/components/todoist/strings.json @@ -0,0 +1,54 @@ +{ + "services": { + "new_task": { + "name": "New task", + "description": "Creates a new task and add it to a project.", + "fields": { + "content": { + "name": "Content", + "description": "The name of the task." + }, + "project": { + "name": "Project", + "description": "The name of the project this task should belong to." + }, + "labels": { + "name": "Labels", + "description": "Any labels that you want to apply to this task, separated by a comma." + }, + "assignee": { + "name": "Assignee", + "description": "A members username of a shared project to assign this task to." + }, + "priority": { + "name": "Priority", + "description": "The priority of this task, from 1 (normal) to 4 (urgent)." + }, + "due_date_string": { + "name": "Due date string", + "description": "The day this task is due, in natural language." + }, + "due_date_lang": { + "name": "Due data language", + "description": "The language of due_date_string." + }, + "due_date": { + "name": "Due date", + "description": "The time this task is due, in format YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS, in UTC timezone." + }, + "reminder_date_string": { + "name": "Reminder date string", + "description": "When should user be reminded of this task, in natural language." + }, + "reminder_date_lang": { + "name": "Reminder data language", + "description": "The language of reminder_date_string." + }, + "reminder_date": { + "name": "Reminder date", + "description": "When should user be reminded of this task, in format YYYY-MM-DDTHH:MM:SS, in UTC timezone." + } + } + } + } +} diff --git a/homeassistant/components/toon/services.yaml b/homeassistant/components/toon/services.yaml index d01cf32994b5ca..1b75dd4957aa1e 100644 --- a/homeassistant/components/toon/services.yaml +++ b/homeassistant/components/toon/services.yaml @@ -1,10 +1,6 @@ update: - name: Update - description: Update all entities with fresh data from Toon fields: display: - name: Display - description: Toon display to update. advanced: true example: eneco-001-123456 selector: diff --git a/homeassistant/components/toon/strings.json b/homeassistant/components/toon/strings.json index 60d5ed3312c27a..620a7f51113c6e 100644 --- a/homeassistant/components/toon/strings.json +++ b/homeassistant/components/toon/strings.json @@ -20,5 +20,17 @@ "no_agreements": "This account has no Toon displays.", "no_url_available": "[%key:common::config_flow::abort::oauth2_no_url_available%]" } + }, + "services": { + "update": { + "name": "Update", + "description": "Updates all entities with fresh data from Toon.", + "fields": { + "display": { + "name": "Display", + "description": "Toon display to update." + } + } + } } } diff --git a/homeassistant/components/totalconnect/services.yaml b/homeassistant/components/totalconnect/services.yaml index 0e8f8f8e217fcf..3ab4faf0c30e82 100644 --- a/homeassistant/components/totalconnect/services.yaml +++ b/homeassistant/components/totalconnect/services.yaml @@ -1,14 +1,10 @@ arm_away_instant: - name: Arm Away Instant - description: Arm Away with zero entry delay. target: entity: integration: totalconnect domain: alarm_control_panel arm_home_instant: - name: Arm Home Instant - description: Arm Home with zero entry delay. target: entity: integration: totalconnect diff --git a/homeassistant/components/totalconnect/strings.json b/homeassistant/components/totalconnect/strings.json index 346ea7ef4030cf..922962c9866291 100644 --- a/homeassistant/components/totalconnect/strings.json +++ b/homeassistant/components/totalconnect/strings.json @@ -39,5 +39,15 @@ } } } + }, + "services": { + "arm_away_instant": { + "name": "Arm away instant", + "description": "Arms Away with zero entry delay." + }, + "arm_home_instant": { + "name": "Arm home instant", + "description": "Arms Home with zero entry delay." + } } } diff --git a/homeassistant/components/tplink/services.yaml b/homeassistant/components/tplink/services.yaml index 16166278565aed..1850df9a06017c 100644 --- a/homeassistant/components/tplink/services.yaml +++ b/homeassistant/components/tplink/services.yaml @@ -1,14 +1,10 @@ sequence_effect: - name: Sequence effect - description: Set a sequence effect target: entity: integration: tplink domain: light fields: sequence: - name: Sequence - description: List of HSV sequences (Max 16) example: | - [340, 20, 50] - [20, 50, 50] @@ -17,16 +13,12 @@ sequence_effect: selector: object: segments: - name: Segments - description: List of Segments (0 for all) example: 0, 2, 4, 6, 8 default: 0 required: false selector: object: brightness: - name: Brightness - description: Initial brightness example: 80 default: 100 required: false @@ -37,8 +29,6 @@ sequence_effect: max: 100 unit_of_measurement: "%" duration: - name: Duration - description: Duration example: 0 default: 0 required: false @@ -49,8 +39,6 @@ sequence_effect: max: 5000 unit_of_measurement: "ms" repeat_times: - name: Repetitions - description: Repetitions (0 for continuous) example: 0 default: 0 required: false @@ -60,8 +48,6 @@ sequence_effect: step: 1 max: 10 transition: - name: Transition - description: Transition example: 2000 default: 0 required: false @@ -72,8 +58,6 @@ sequence_effect: max: 6000 unit_of_measurement: "ms" spread: - name: Spread - description: Speed of spread example: 1 default: 0 required: false @@ -83,8 +67,6 @@ sequence_effect: step: 1 max: 16 direction: - name: Direction - description: Direction example: 1 default: 4 required: false @@ -94,21 +76,17 @@ sequence_effect: step: 1 max: 4 random_effect: - name: Random effect - description: Set a random effect target: entity: integration: tplink domain: light fields: init_states: - description: Initial HSV sequence example: [199, 99, 96] required: true selector: object: backgrounds: - description: List of HSV sequences (Max 16) example: | - [199, 89, 50] - [160, 50, 50] @@ -117,14 +95,12 @@ random_effect: selector: object: segments: - description: List of segments (0 for all) example: 0, 2, 4, 6, 8 default: 0 required: false selector: object: brightness: - description: Initial brightness example: 90 default: 100 required: false @@ -135,7 +111,6 @@ random_effect: max: 100 unit_of_measurement: "%" duration: - description: Duration example: 0 default: 0 required: false @@ -146,7 +121,6 @@ random_effect: max: 5000 unit_of_measurement: "ms" transition: - description: Transition example: 2000 default: 0 required: false @@ -157,7 +131,6 @@ random_effect: max: 6000 unit_of_measurement: "ms" fadeoff: - description: Fade off example: 2000 default: 0 required: false @@ -168,31 +141,26 @@ random_effect: max: 3000 unit_of_measurement: "ms" hue_range: - description: Range of hue example: 340, 360 required: false selector: object: saturation_range: - description: Range of saturation example: 40, 95 required: false selector: object: brightness_range: - description: Range of brightness example: 90, 100 required: false selector: object: transition_range: - description: Range of transition example: 2000, 6000 required: false selector: object: random_seed: - description: Random seed example: 80 default: 100 required: false diff --git a/homeassistant/components/tplink/strings.json b/homeassistant/components/tplink/strings.json index afc595a3adcec1..b5279804d0a3d3 100644 --- a/homeassistant/components/tplink/strings.json +++ b/homeassistant/components/tplink/strings.json @@ -24,5 +24,99 @@ "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", "no_devices_found": "[%key:common::config_flow::abort::no_devices_found%]" } + }, + "services": { + "sequence_effect": { + "name": "Sequence effect", + "description": "Sets a sequence effect.", + "fields": { + "sequence": { + "name": "Sequence", + "description": "List of HSV sequences (Max 16)." + }, + "segments": { + "name": "Segments", + "description": "List of Segments (0 for all)." + }, + "brightness": { + "name": "Brightness", + "description": "Initial brightness." + }, + "duration": { + "name": "Duration", + "description": "Duration." + }, + "repeat_times": { + "name": "Repetitions", + "description": "Repetitions (0 for continuous)." + }, + "transition": { + "name": "Transition", + "description": "Transition." + }, + "spread": { + "name": "Spread", + "description": "Speed of spread." + }, + "direction": { + "name": "Direction", + "description": "Direction." + } + } + }, + "random_effect": { + "name": "Random effect", + "description": "Sets a random effect.", + "fields": { + "init_states": { + "name": "Initial states", + "description": "Initial HSV sequence." + }, + "backgrounds": { + "name": "Backgrounds", + "description": "List of HSV sequences (Max 16)." + }, + "segments": { + "name": "Segments", + "description": "List of segments (0 for all)." + }, + "brightness": { + "name": "Brightness", + "description": "Initial brightness." + }, + "duration": { + "name": "Duration", + "description": "Duration." + }, + "transition": { + "name": "Transition", + "description": "Transition." + }, + "fadeoff": { + "name": "Fade off", + "description": "Fade off." + }, + "hue_range": { + "name": "Hue range", + "description": "Range of hue." + }, + "saturation_range": { + "name": "Saturation range", + "description": "Range of saturation." + }, + "brightness_range": { + "name": "Brightness range", + "description": "Range of brightness." + }, + "transition_range": { + "name": "Transition range", + "description": "Range of transition." + }, + "random_seed": { + "name": "Random seed", + "description": "Random seed." + } + } + } } } diff --git a/homeassistant/components/transmission/services.yaml b/homeassistant/components/transmission/services.yaml index 34a885284119d2..2d61bda442feb0 100644 --- a/homeassistant/components/transmission/services.yaml +++ b/homeassistant/components/transmission/services.yaml @@ -1,75 +1,49 @@ add_torrent: - name: Add torrent - description: Add a new torrent to download (URL, magnet link or Base64 encoded). fields: entry_id: - name: Transmission entry - description: Config entry id selector: config_entry: integration: transmission torrent: - name: Torrent - description: URL, magnet link or Base64 encoded file. required: true example: http://releases.ubuntu.com/19.04/ubuntu-19.04-desktop-amd64.iso.torrent selector: text: remove_torrent: - name: Remove torrent - description: Remove a torrent fields: entry_id: - name: Transmission entry - description: Config entry id selector: config_entry: integration: transmission id: - name: ID - description: ID of a torrent required: true example: 123 selector: text: delete_data: - name: Delete data - description: Delete torrent data default: false selector: boolean: start_torrent: - name: Start torrent - description: Start a torrent fields: entry_id: - name: Transmission entry - description: Config entry id selector: config_entry: integration: transmission id: - name: ID - description: ID of a torrent example: 123 selector: text: stop_torrent: - name: Stop torrent - description: Stop a torrent fields: entry_id: - name: Transmission entry - description: Config entry id selector: config_entry: integration: transmission id: - name: ID - description: ID of a torrent required: true example: 123 selector: diff --git a/homeassistant/components/transmission/strings.json b/homeassistant/components/transmission/strings.json index e2c144d54232f8..c3fdcc8f1f4d84 100644 --- a/homeassistant/components/transmission/strings.json +++ b/homeassistant/components/transmission/strings.json @@ -52,5 +52,67 @@ } } } + }, + "services": { + "add_torrent": { + "name": "Add torrent", + "description": "Adds a new torrent to download (URL, magnet link or Base64 encoded).", + "fields": { + "entry_id": { + "name": "Transmission entry", + "description": "Config entry id." + }, + "torrent": { + "name": "Torrent", + "description": "URL, magnet link or Base64 encoded file." + } + } + }, + "remove_torrent": { + "name": "Remove torrent", + "description": "Removes a torrent.", + "fields": { + "entry_id": { + "name": "Transmission entry", + "description": "Config entry id." + }, + "id": { + "name": "ID", + "description": "ID of a torrent." + }, + "delete_data": { + "name": "Delete data", + "description": "Delete torrent data." + } + } + }, + "start_torrent": { + "name": "Start torrent", + "description": "Starts a torrent.", + "fields": { + "entry_id": { + "name": "Transmission entry", + "description": "Config entry id." + }, + "id": { + "name": "ID", + "description": "ID of a torrent." + } + } + }, + "stop_torrent": { + "name": "Stop torrent", + "description": "Stops a torrent.", + "fields": { + "entry_id": { + "name": "Transmission entry", + "description": "Config entry id." + }, + "id": { + "name": "ID", + "description": "ID of a torrent." + } + } + } } } diff --git a/homeassistant/components/unifi/services.yaml b/homeassistant/components/unifi/services.yaml index c6a4de3072a10e..fd69b8eb708ac1 100644 --- a/homeassistant/components/unifi/services.yaml +++ b/homeassistant/components/unifi/services.yaml @@ -1,15 +1,9 @@ reconnect_client: - name: Reconnect wireless client - description: Try to get wireless client to reconnect to UniFi Network fields: device_id: - name: Device - description: Try reconnect client to wireless network required: true selector: device: integration: unifi remove_clients: - name: Remove clients from the UniFi Network - description: Clean up clients that has only been associated with the controller for a short period of time. diff --git a/homeassistant/components/unifi/strings.json b/homeassistant/components/unifi/strings.json index 02b64f3c50ed1b..6afae5ffe7b83e 100644 --- a/homeassistant/components/unifi/strings.json +++ b/homeassistant/components/unifi/strings.json @@ -68,5 +68,21 @@ "title": "UniFi Network options 3/3" } } + }, + "services": { + "reconnect_client": { + "name": "Reconnect wireless client", + "description": "Tries to get wireless client to reconnect to UniFi Network.", + "fields": { + "device_id": { + "name": "Device", + "description": "Try reconnect client to wireless network." + } + } + }, + "remove_clients": { + "name": "Remove clients from the UniFi Network", + "description": "Cleans up clients that has only been associated with the controller for a short period of time." + } } } diff --git a/homeassistant/components/unifiprotect/services.yaml b/homeassistant/components/unifiprotect/services.yaml index 9f9031d6543019..6998f540471cc3 100644 --- a/homeassistant/components/unifiprotect/services.yaml +++ b/homeassistant/components/unifiprotect/services.yaml @@ -1,65 +1,42 @@ add_doorbell_text: - name: Add Custom Doorbell Text - description: Adds a new custom message for Doorbells. fields: device_id: - name: UniFi Protect NVR - description: Any device from the UniFi Protect instance you want to change. In case you have multiple Protect Instances. required: true selector: device: integration: unifiprotect message: - name: Custom Message - description: New custom message to add for Doorbells. Must be less than 30 characters. example: Come In required: true selector: text: remove_doorbell_text: - name: Remove Custom Doorbell Text - description: Removes an existing message for Doorbells. fields: device_id: - name: UniFi Protect NVR - description: Any device from the UniFi Protect instance you want to change. In case you have multiple Protect Instances. required: true selector: device: integration: unifiprotect message: - name: Custom Message - description: Existing custom message to remove for Doorbells. example: Go Away! required: true selector: text: set_default_doorbell_text: - name: Set Default Doorbell Text - description: Sets the default doorbell message. This will be the message that is automatically selected when a message "expires". fields: device_id: - name: UniFi Protect NVR - description: Any device from the UniFi Protect instance you want to change. In case you have multiple Protect Instances. required: true selector: device: integration: unifiprotect message: - name: Default Message - description: The default message for your Doorbell. Must be less than 30 characters. example: Welcome! required: true selector: text: set_chime_paired_doorbells: - name: Set Chime Paired Doorbells - description: > - Use to set the paired doorbell(s) with a smart chime. fields: device_id: - name: Chime - description: The Chimes to link to the doorbells to required: true selector: device: @@ -67,8 +44,6 @@ set_chime_paired_doorbells: entity: device_class: unifiprotect__chime_button doorbells: - name: Doorbells - description: The Doorbells to link to the chime example: "binary_sensor.front_doorbell_doorbell" required: false selector: diff --git a/homeassistant/components/unifiprotect/strings.json b/homeassistant/components/unifiprotect/strings.json index b7be12233df742..fd2287e08be23f 100644 --- a/homeassistant/components/unifiprotect/strings.json +++ b/homeassistant/components/unifiprotect/strings.json @@ -85,5 +85,63 @@ } } } + }, + "services": { + "add_doorbell_text": { + "name": "Add custom doorbell text", + "description": "Adds a new custom message for doorbells.", + "fields": { + "device_id": { + "name": "UniFi Protect NVR", + "description": "Any device from the UniFi Protect instance you want to change. In case you have multiple Protect Instances." + }, + "message": { + "name": "Custom message", + "description": "New custom message to add for doorbells. Must be less than 30 characters." + } + } + }, + "remove_doorbell_text": { + "name": "Remove custom doorbell text", + "description": "Removes an existing message for doorbells.", + "fields": { + "device_id": { + "name": "UniFi Protect NVR", + "description": "Any device from the UniFi Protect instance you want to change. In case you have multiple Protect Instances." + }, + "message": { + "name": "Custom message", + "description": "Existing custom message to remove for doorbells." + } + } + }, + "set_default_doorbell_text": { + "name": "Set default doorbell text", + "description": "Sets the default doorbell message. This will be the message that is automatically selected when a message \"expires\".", + "fields": { + "device_id": { + "name": "UniFi Protect NVR", + "description": "Any device from the UniFi Protect instance you want to change. In case you have multiple Protect Instances." + }, + "message": { + "name": "Default message", + "description": "The default message for your doorbell. Must be less than 30 characters." + } + } + }, + "set_chime_paired_doorbells": { + "name": "Set chime paired doorbells", + "description": "Use to set the paired doorbell(s) with a smart chime.", + "fields": { + "device_id": { + "name": "Chime", + "description": "The chimes to link to the doorbells to." + }, + "doorbells": { + "name": "Doorbells", + "description": "The doorbells to link to the chime." + } + } + } } } diff --git a/homeassistant/components/upb/services.yaml b/homeassistant/components/upb/services.yaml index af8eb81d9b04f9..cf415705d72e95 100644 --- a/homeassistant/components/upb/services.yaml +++ b/homeassistant/components/upb/services.yaml @@ -1,29 +1,21 @@ light_fade_start: - name: Start light fade - description: Start fading a light either up or down from current brightness. target: entity: integration: upb domain: light fields: brightness: - name: Brightness - description: Number indicating brightness, where 0 turns the light off, 1 is the minimum brightness and 255 is the maximum brightness. selector: number: min: 0 max: 255 brightness_pct: - name: Brightness percentage - description: Number indicating percentage of full brightness, where 0 turns the light off, 1 is the minimum brightness and 100 is the maximum brightness. selector: number: min: 0 max: 100 unit_of_measurement: "%" rate: - name: Rate - description: Rate for light to transition to new brightness default: -1 selector: number: @@ -33,24 +25,18 @@ light_fade_start: unit_of_measurement: seconds light_fade_stop: - name: Stop light fade - description: Stop a light fade. target: entity: integration: upb domain: light light_blink: - name: Blink light - description: Blink a light target: entity: integration: upb domain: light fields: rate: - name: Rate - description: Amount of time that the link flashes on. default: 0.5 selector: number: @@ -60,39 +46,29 @@ light_blink: unit_of_measurement: seconds link_deactivate: - name: Deactivate link - description: Deactivate a UPB scene. target: entity: integration: upb domain: light link_goto: - name: Go to link - description: Set scene to brightness. target: entity: integration: upb domain: scene fields: brightness: - name: Brightness - description: Number indicating brightness, where 0 turns the scene off, 1 is the minimum brightness and 255 is the maximum brightness. selector: number: min: 0 max: 255 brightness_pct: - name: Brightness percentage - description: Number indicating percentage of full brightness, where 0 turns the scene off, 1 is the minimum brightness and 100 is the maximum brightness. selector: number: min: 0 max: 100 unit_of_measurement: "%" rate: - name: Rate - description: Amount of time for scene to transition to new brightness selector: number: min: -1 @@ -101,31 +77,23 @@ link_goto: unit_of_measurement: seconds link_fade_start: - name: Start link fade - description: Start fading a link either up or down from current brightness. target: entity: integration: upb domain: scene fields: brightness: - name: Brightness - description: Number indicating brightness, where 0 turns the scene off, 1 is the minimum brightness and 255 is the maximum brightness. selector: number: min: 0 max: 255 brightness_pct: - name: Brightness percentage - description: Number indicating percentage of full brightness, where 0 turns the scene off, 1 is the minimum brightness and 100 is the maximum brightness. selector: number: min: 0 max: 100 unit_of_measurement: "%" rate: - name: Rate - description: Amount of time for scene to transition to new brightness selector: number: min: -1 @@ -134,24 +102,18 @@ link_fade_start: unit_of_measurement: seconds link_fade_stop: - name: Stop link fade - description: Stop a link fade. target: entity: integration: upb domain: scene link_blink: - name: Blink link - description: Blink a link. target: entity: integration: upb domain: scene fields: blink_rate: - name: Blink rate - description: Amount of time that the link flashes on. default: 0.5 selector: number: diff --git a/homeassistant/components/upb/strings.json b/homeassistant/components/upb/strings.json index 9b2cc0a1b12f16..b5b6dea93d5f7c 100644 --- a/homeassistant/components/upb/strings.json +++ b/homeassistant/components/upb/strings.json @@ -19,5 +19,93 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" } + }, + "services": { + "light_fade_start": { + "name": "Start light fade", + "description": "Starts fading a light either up or down from current brightness.", + "fields": { + "brightness": { + "name": "Brightness", + "description": "Number indicating brightness, where 0 turns the light off, 1 is the minimum brightness and 255 is the maximum brightness." + }, + "brightness_pct": { + "name": "Brightness percentage", + "description": "Number indicating percentage of full brightness, where 0 turns the light off, 1 is the minimum brightness and 100 is the maximum brightness." + }, + "rate": { + "name": "Rate", + "description": "Rate for light to transition to new brightness." + } + } + }, + "light_fade_stop": { + "name": "Stop light fade", + "description": "Stops a light fade." + }, + "light_blink": { + "name": "Blink light", + "description": "Blinks a light.", + "fields": { + "rate": { + "name": "Rate", + "description": "Amount of time that the link flashes on." + } + } + }, + "link_deactivate": { + "name": "Deactivate link", + "description": "Deactivates a UPB scene." + }, + "link_goto": { + "name": "Go to link", + "description": "Set scene to brightness.", + "fields": { + "brightness": { + "name": "Brightness", + "description": "Number indicating brightness, where 0 turns the scene off, 1 is the minimum brightness and 255 is the maximum brightness." + }, + "brightness_pct": { + "name": "Brightness percentage", + "description": "Number indicating percentage of full brightness, where 0 turns the scene off, 1 is the minimum brightness and 100 is the maximum brightness." + }, + "rate": { + "name": "Rate", + "description": "Amount of time for scene to transition to new brightness." + } + } + }, + "link_fade_start": { + "name": "Start link fade", + "description": "Starts fading a link either up or down from current brightness.", + "fields": { + "brightness": { + "name": "Brightness", + "description": "Number indicating brightness, where 0 turns the scene off, 1 is the minimum brightness and 255 is the maximum brightness." + }, + "brightness_pct": { + "name": "Brightness percentage", + "description": "Number indicating percentage of full brightness, where 0 turns the scene off, 1 is the minimum brightness and 100 is the maximum brightness." + }, + "rate": { + "name": "Rate", + "description": "Amount of time for scene to transition to new brightness." + } + } + }, + "link_fade_stop": { + "name": "Stop link fade", + "description": "Stops a link fade." + }, + "link_blink": { + "name": "Blink link", + "description": "Blinks a link.", + "fields": { + "blink_rate": { + "name": "Blink rate", + "description": "Amount of time that the link flashes on." + } + } + } } } diff --git a/homeassistant/components/utility_meter/services.yaml b/homeassistant/components/utility_meter/services.yaml index 4252f7961991ba..918c51cee390a0 100644 --- a/homeassistant/components/utility_meter/services.yaml +++ b/homeassistant/components/utility_meter/services.yaml @@ -1,23 +1,17 @@ # Describes the format for available switch services reset: - name: Reset - description: Resets all counters of a utility meter. target: entity: domain: select calibrate: - name: Calibrate - description: Calibrates a utility meter sensor. target: entity: domain: sensor integration: utility_meter fields: value: - name: Value - description: Value to which set the meter example: "100" required: true selector: diff --git a/homeassistant/components/utility_meter/strings.json b/homeassistant/components/utility_meter/strings.json index 1eeacbae800364..09b9dd0954046a 100644 --- a/homeassistant/components/utility_meter/strings.json +++ b/homeassistant/components/utility_meter/strings.json @@ -52,5 +52,21 @@ "yearly": "Yearly" } } + }, + "services": { + "reset": { + "name": "Reset", + "description": "Resets all counters of a utility meter." + }, + "calibrate": { + "name": "Calibrate", + "description": "Calibrates a utility meter sensor.", + "fields": { + "value": { + "name": "Value", + "description": "Value to which set the meter." + } + } + } } } diff --git a/homeassistant/components/vallox/services.yaml b/homeassistant/components/vallox/services.yaml index 15ce6c88b5581b..e6bd3edad116ca 100644 --- a/homeassistant/components/vallox/services.yaml +++ b/homeassistant/components/vallox/services.yaml @@ -1,10 +1,6 @@ set_profile_fan_speed_home: - name: Set profile fan speed home - description: Set the fan speed of the Home profile. fields: fan_speed: - name: Fan speed - description: Fan speed. required: true selector: number: @@ -13,12 +9,8 @@ set_profile_fan_speed_home: unit_of_measurement: "%" set_profile_fan_speed_away: - name: Set profile fan speed away - description: Set the fan speed of the Away profile. fields: fan_speed: - name: Fan speed - description: Fan speed. required: true selector: number: @@ -27,12 +19,8 @@ set_profile_fan_speed_away: unit_of_measurement: "%" set_profile_fan_speed_boost: - name: Set profile fan speed boost - description: Set the fan speed of the Boost profile. fields: fan_speed: - name: Fan speed - description: Fan speed. required: true selector: number: diff --git a/homeassistant/components/vallox/strings.json b/homeassistant/components/vallox/strings.json index cada5a7febdf56..b33cef0026aaf1 100644 --- a/homeassistant/components/vallox/strings.json +++ b/homeassistant/components/vallox/strings.json @@ -18,5 +18,37 @@ "invalid_host": "[%key:common::config_flow::error::invalid_host%]", "unknown": "[%key:common::config_flow::error::unknown%]" } + }, + "services": { + "set_profile_fan_speed_home": { + "name": "Set profile fan speed home", + "description": "Sets the fan speed of the Home profile.", + "fields": { + "fan_speed": { + "name": "Fan speed", + "description": "Fan speed." + } + } + }, + "set_profile_fan_speed_away": { + "name": "Set profile fan speed away", + "description": "Sets the fan speed of the Away profile.", + "fields": { + "fan_speed": { + "name": "Fan speed", + "description": "Fan speed." + } + } + }, + "set_profile_fan_speed_boost": { + "name": "Set profile fan speed boost", + "description": "Sets the fan speed of the Boost profile.", + "fields": { + "fan_speed": { + "name": "Fan speed", + "description": "Fan speed." + } + } + } } } diff --git a/homeassistant/components/velbus/services.yaml b/homeassistant/components/velbus/services.yaml index 32cda00f708301..e3ecc3556f01b0 100644 --- a/homeassistant/components/velbus/services.yaml +++ b/homeassistant/components/velbus/services.yaml @@ -1,10 +1,6 @@ sync_clock: - name: Sync clock - description: Sync the velbus modules clock to the Home Assistant clock, this is the same as the 'sync clock' from VelbusLink fields: interface: - name: Interface - description: The velbus interface to send the command to, this will be the same value as used during configuration required: true example: "192.168.1.5:27015" default: "" @@ -12,12 +8,8 @@ sync_clock: text: scan: - name: Scan - description: Scan the velbus modules, this will be need if you see unknown module warnings in the logs, or when you added new modules fields: interface: - name: Interface - description: The velbus interface to send the command to, this will be the same value as used during configuration required: true example: "192.168.1.5:27015" default: "" @@ -25,22 +17,14 @@ scan: text: clear_cache: - name: Clear cache - description: Clears the velbuscache and then starts a new scan fields: interface: - name: Interface - description: The velbus interface to send the command to, this will be the same value as used during configuration required: true example: "192.168.1.5:27015" default: "" selector: text: address: - name: Address - description: > - The module address in decimal format, if this is provided we only clear this module, if nothing is provided we clear the whole cache directory (all modules) - The decimal addresses are displayed in front of the modules listed at the integration page. required: false selector: number: @@ -48,34 +32,20 @@ clear_cache: max: 254 set_memo_text: - name: Set memo text - description: > - Set the memo text to the display of modules like VMBGPO, VMBGPOD - Be sure the page(s) of the module is configured to display the memo text. fields: interface: - name: Interface - description: The velbus interface to send the command to, this will be the same value as used during configuration required: true example: "192.168.1.5:27015" default: "" selector: text: address: - name: Address - description: > - The module address in decimal format. - The decimal addresses are displayed in front of the modules listed at the integration page. required: true selector: number: min: 1 max: 254 memo_text: - name: Memo text - description: > - The actual text to be displayed. - Text is limited to 64 characters. example: "Do not forget trash" default: "" selector: diff --git a/homeassistant/components/velbus/strings.json b/homeassistant/components/velbus/strings.json index 6eb44d8cb0c0eb..bef853001a1744 100644 --- a/homeassistant/components/velbus/strings.json +++ b/homeassistant/components/velbus/strings.json @@ -16,5 +16,59 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" } + }, + "services": { + "sync_clock": { + "name": "Sync clock", + "description": "Syncs the velbus modules clock to the Home Assistant clock, this is the same as the 'sync clock' from VelbusLink.", + "fields": { + "interface": { + "name": "Interface", + "description": "The velbus interface to send the command to, this will be the same value as used during configuration." + } + } + }, + "scan": { + "name": "Scan", + "description": "Scans the velbus modules, this will be need if you see unknown module warnings in the logs, or when you added new modules.", + "fields": { + "interface": { + "name": "Interface", + "description": "The velbus interface to send the command to, this will be the same value as used during configuration." + } + } + }, + "clear_cache": { + "name": "Clear cache", + "description": "Clears the velbuscache and then starts a new scan.", + "fields": { + "interface": { + "name": "Interface", + "description": "The velbus interface to send the command to, this will be the same value as used during configuration." + }, + "address": { + "name": "Address", + "description": "The module address in decimal format, if this is provided we only clear this module, if nothing is provided we clear the whole cache directory (all modules) The decimal addresses are displayed in front of the modules listed at the integration page.\n." + } + } + }, + "set_memo_text": { + "name": "Set memo text", + "description": "Sets the memo text to the display of modules like VMBGPO, VMBGPOD Be sure the page(s) of the module is configured to display the memo text.\n.", + "fields": { + "interface": { + "name": "Interface", + "description": "The velbus interface to send the command to, this will be the same value as used during configuration." + }, + "address": { + "name": "Address", + "description": "The module address in decimal format. The decimal addresses are displayed in front of the modules listed at the integration page.\n." + }, + "memo_text": { + "name": "Memo text", + "description": "The actual text to be displayed. Text is limited to 64 characters.\n." + } + } + } } } diff --git a/homeassistant/components/velux/services.yaml b/homeassistant/components/velux/services.yaml index 46aee795890ad2..7aee1694061aae 100644 --- a/homeassistant/components/velux/services.yaml +++ b/homeassistant/components/velux/services.yaml @@ -1,5 +1,3 @@ # Velux Integration services reboot_gateway: - name: Reboot gateway - description: Reboots the KLF200 Gateway. diff --git a/homeassistant/components/velux/strings.json b/homeassistant/components/velux/strings.json new file mode 100644 index 00000000000000..6a7e8c6e1ec963 --- /dev/null +++ b/homeassistant/components/velux/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "reboot_gateway": { + "name": "Reboot gateway", + "description": "Reboots the KLF200 Gateway." + } + } +} diff --git a/homeassistant/components/verisure/services.yaml b/homeassistant/components/verisure/services.yaml index 2a4e2a008bee65..ccfc7726bc6455 100644 --- a/homeassistant/components/verisure/services.yaml +++ b/homeassistant/components/verisure/services.yaml @@ -1,22 +1,16 @@ capture_smartcam: - name: Capture SmartCam image - description: Capture a new image from a Verisure SmartCam target: entity: integration: verisure domain: camera enable_autolock: - name: Enable autolock - description: Enable autolock of a Verisure Lockguard Smartlock target: entity: integration: verisure domain: lock disable_autolock: - name: Disable autolock - description: Disable autolock of a Verisure Lockguard Smartlock target: entity: integration: verisure diff --git a/homeassistant/components/verisure/strings.json b/homeassistant/components/verisure/strings.json index 85b3f4015b54bd..335daa68ee8a70 100644 --- a/homeassistant/components/verisure/strings.json +++ b/homeassistant/components/verisure/strings.json @@ -63,5 +63,19 @@ "name": "Ethernet status" } } + }, + "services": { + "capture_smartcam": { + "name": "Capture SmartCam image", + "description": "Captures a new image from a Verisure SmartCam." + }, + "enable_autolock": { + "name": "Enable autolock", + "description": "Enables autolock of a Verisure Lockguard Smartlock." + }, + "disable_autolock": { + "name": "Disable autolock", + "description": "Disables autolock of a Verisure Lockguard Smartlock." + } } } diff --git a/homeassistant/components/vesync/services.yaml b/homeassistant/components/vesync/services.yaml index da264ea3b5d9ee..52ee0382dbe029 100644 --- a/homeassistant/components/vesync/services.yaml +++ b/homeassistant/components/vesync/services.yaml @@ -1,3 +1 @@ update_devices: - name: Update devices - description: Add new VeSync devices to Home Assistant diff --git a/homeassistant/components/vesync/strings.json b/homeassistant/components/vesync/strings.json index 8359691effef14..08cbdf943f67b9 100644 --- a/homeassistant/components/vesync/strings.json +++ b/homeassistant/components/vesync/strings.json @@ -15,5 +15,11 @@ "abort": { "single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]" } + }, + "services": { + "update_devices": { + "name": "Update devices", + "description": "Adds new VeSync devices to Home Assistant." + } } } diff --git a/homeassistant/components/vicare/services.yaml b/homeassistant/components/vicare/services.yaml index 1fc1e61b6eeec3..b4df8a1bb0e388 100644 --- a/homeassistant/components/vicare/services.yaml +++ b/homeassistant/components/vicare/services.yaml @@ -1,14 +1,10 @@ set_vicare_mode: - name: Set vicare mode - description: Set a ViCare mode. target: entity: integration: vicare domain: climate fields: vicare_mode: - name: Vicare Mode - description: ViCare mode. required: true selector: select: diff --git a/homeassistant/components/vicare/strings.json b/homeassistant/components/vicare/strings.json index d54956f3e103d6..0700d5d6f0e630 100644 --- a/homeassistant/components/vicare/strings.json +++ b/homeassistant/components/vicare/strings.json @@ -19,5 +19,17 @@ "single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]", "unknown": "[%key:common::config_flow::error::unknown%]" } + }, + "services": { + "set_vicare_mode": { + "name": "Set ViCare mode", + "description": "Set a ViCare mode.", + "fields": { + "vicare_mode": { + "name": "ViCare mode", + "description": "ViCare mode." + } + } + } } } diff --git a/homeassistant/components/vizio/services.yaml b/homeassistant/components/vizio/services.yaml index 7a2ea859b7dab5..2f5da4659f0fe9 100644 --- a/homeassistant/components/vizio/services.yaml +++ b/homeassistant/components/vizio/services.yaml @@ -1,32 +1,20 @@ update_setting: - name: Update setting - description: Update the value of a setting on a Vizio media player device. target: entity: integration: vizio domain: media_player fields: setting_type: - name: Setting type - description: - The type of setting to be changed. Available types are listed in the - 'setting_types' property. required: true example: "audio" selector: text: setting_name: - name: Setting name - description: - The name of the setting to be changed. Available settings for a given - setting_type are listed in the '_settings' property. required: true example: "eq" selector: text: new_value: - name: New value - description: The new value for the setting. required: true example: "Music" selector: diff --git a/homeassistant/components/vizio/strings.json b/homeassistant/components/vizio/strings.json index 665e03b531ac6a..314f6f8b4e5f8f 100644 --- a/homeassistant/components/vizio/strings.json +++ b/homeassistant/components/vizio/strings.json @@ -50,5 +50,25 @@ } } } + }, + "services": { + "update_setting": { + "name": "Update setting", + "description": "Updates the value of a setting on a Vizio media player device.", + "fields": { + "setting_type": { + "name": "Setting type", + "description": "The type of setting to be changed. Available types are listed in the 'setting_types' property." + }, + "setting_name": { + "name": "Setting name", + "description": "The name of the setting to be changed. Available settings for a given setting_type are listed in the '[setting_type]_settings' property." + }, + "new_value": { + "name": "New value", + "description": "The new value for the setting." + } + } + } } } From ce3c23cb3ac4a0c895cafea16984e96dff4a7811 Mon Sep 17 00:00:00 2001 From: ollo69 <60491700+ollo69@users.noreply.github.com> Date: Wed, 12 Jul 2023 10:56:08 +0200 Subject: [PATCH 071/154] Add Nut commands to diagnostics data (#96285) * Add Nut commands to diagnostics data * Add test for diagnostics --- homeassistant/components/nut/diagnostics.py | 9 ++++- tests/components/nut/test_diagnostics.py | 43 +++++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 tests/components/nut/test_diagnostics.py diff --git a/homeassistant/components/nut/diagnostics.py b/homeassistant/components/nut/diagnostics.py index e8c0a0711dc78b..9ee430a655b0c8 100644 --- a/homeassistant/components/nut/diagnostics.py +++ b/homeassistant/components/nut/diagnostics.py @@ -12,7 +12,7 @@ from homeassistant.helpers import device_registry as dr, entity_registry as er from . import PyNUTData -from .const import DOMAIN, PYNUT_DATA, PYNUT_UNIQUE_ID +from .const import DOMAIN, PYNUT_DATA, PYNUT_UNIQUE_ID, USER_AVAILABLE_COMMANDS TO_REDACT = {CONF_PASSWORD, CONF_USERNAME} @@ -26,7 +26,12 @@ async def async_get_config_entry_diagnostics( # Get information from Nut library nut_data: PyNUTData = hass_data[PYNUT_DATA] - data["nut_data"] = {"ups_list": nut_data.ups_list, "status": nut_data.status} + nut_cmd: set[str] = hass_data[USER_AVAILABLE_COMMANDS] + data["nut_data"] = { + "ups_list": nut_data.ups_list, + "status": nut_data.status, + "commands": nut_cmd, + } # Gather information how this Nut device is represented in Home Assistant device_registry = dr.async_get(hass) diff --git a/tests/components/nut/test_diagnostics.py b/tests/components/nut/test_diagnostics.py new file mode 100644 index 00000000000000..f91269f5196053 --- /dev/null +++ b/tests/components/nut/test_diagnostics.py @@ -0,0 +1,43 @@ +"""Tests for the diagnostics data provided by the Nut integration.""" + +from homeassistant.components.diagnostics import async_redact_data +from homeassistant.components.nut.diagnostics import TO_REDACT +from homeassistant.core import HomeAssistant + +from .util import async_init_integration + +from tests.components.diagnostics import get_diagnostics_for_config_entry +from tests.typing import ClientSessionGenerator + + +async def test_diagnostics( + hass: HomeAssistant, + hass_client: ClientSessionGenerator, +) -> None: + """Test diagnostics.""" + list_commands: set[str] = ["beeper.enable"] + list_commands_return_value = { + supported_command: supported_command for supported_command in list_commands + } + + mock_config_entry = await async_init_integration( + hass, + username="someuser", + password="somepassword", + list_vars={"ups.status": "OL"}, + list_ups={"ups1": "UPS 1"}, + list_commands_return_value=list_commands_return_value, + ) + + entry_dict = async_redact_data(mock_config_entry.as_dict(), TO_REDACT) + nut_data_dict = { + "ups_list": {"ups1": "UPS 1"}, + "status": {"ups.status": "OL"}, + "commands": list_commands, + } + + result = await get_diagnostics_for_config_entry( + hass, hass_client, mock_config_entry + ) + assert result["entry"] == entry_dict + assert result["nut_data"] == nut_data_dict From a3a2e6cc8dfac9889dde2ed52cfc8e93fb7d6a4e Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 12:23:39 +0200 Subject: [PATCH 072/154] Migrate time services to support translations (#96402) --- homeassistant/components/time/services.yaml | 4 ---- homeassistant/components/time/strings.json | 12 ++++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/time/services.yaml b/homeassistant/components/time/services.yaml index a8c843ab55ac1d..ee3d9150870ec6 100644 --- a/homeassistant/components/time/services.yaml +++ b/homeassistant/components/time/services.yaml @@ -1,13 +1,9 @@ set_value: - name: Set Time - description: Set the time for a time entity. target: entity: domain: time fields: time: - name: Time - description: The time to set. required: true example: "22:15" selector: diff --git a/homeassistant/components/time/strings.json b/homeassistant/components/time/strings.json index e8d92a30e2eac8..1b7c53b1a8a80e 100644 --- a/homeassistant/components/time/strings.json +++ b/homeassistant/components/time/strings.json @@ -4,5 +4,17 @@ "_": { "name": "[%key:component::time::title%]" } + }, + "services": { + "set_value": { + "name": "Set Time", + "description": "Sets the time.", + "fields": { + "time": { + "name": "Time", + "description": "The time to set." + } + } + } } } From 7bc90297d25133ff5ad739955c91aa723fbb7d59 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 12:31:26 +0200 Subject: [PATCH 073/154] Migrate integration services (G-H) to support translations (#96372) --- .../components/geniushub/services.yaml | 23 ---- .../components/geniushub/strings.json | 46 +++++++ homeassistant/components/google/services.yaml | 36 ----- homeassistant/components/google/strings.json | 78 +++++++++++ .../components/google_assistant/services.yaml | 4 - .../components/google_assistant/strings.json | 14 ++ .../google_assistant_sdk/services.yaml | 6 - .../google_assistant_sdk/strings.json | 16 +++ .../components/google_mail/services.yaml | 18 --- .../components/google_mail/strings.json | 40 ++++++ .../components/google_sheets/services.yaml | 8 -- .../components/google_sheets/strings.json | 20 +++ .../components/guardian/services.yaml | 22 --- .../components/guardian/strings.json | 52 +++++++ .../components/habitica/services.yaml | 8 -- .../components/habitica/strings.json | 24 +++- .../components/harmony/services.yaml | 6 - homeassistant/components/harmony/strings.json | 16 +++ .../components/hdmi_cec/services.yaml | 33 ----- .../components/hdmi_cec/strings.json | 70 ++++++++++ homeassistant/components/heos/services.yaml | 8 -- homeassistant/components/heos/strings.json | 20 +++ homeassistant/components/hive/services.yaml | 24 ---- homeassistant/components/hive/strings.json | 58 ++++++++ .../components/home_connect/services.yaml | 56 -------- .../components/home_connect/strings.json | 128 ++++++++++++++++++ .../components/homekit/services.yaml | 7 - homeassistant/components/homekit/strings.json | 18 ++- .../components/homematic/services.yaml | 57 -------- .../components/homematic/strings.json | 126 +++++++++++++++++ .../homematicip_cloud/services.yaml | 46 ------- .../components/homematicip_cloud/strings.json | 110 +++++++++++++++ homeassistant/components/html5/services.yaml | 6 - homeassistant/components/html5/strings.json | 18 +++ .../components/huawei_lte/services.yaml | 19 --- .../components/huawei_lte/strings.json | 42 ++++++ homeassistant/components/hue/services.yaml | 19 --- homeassistant/components/hue/strings.json | 43 +++++- 38 files changed, 934 insertions(+), 411 deletions(-) create mode 100644 homeassistant/components/geniushub/strings.json create mode 100644 homeassistant/components/google_assistant/strings.json create mode 100644 homeassistant/components/hdmi_cec/strings.json create mode 100644 homeassistant/components/homematic/strings.json create mode 100644 homeassistant/components/html5/strings.json diff --git a/homeassistant/components/geniushub/services.yaml b/homeassistant/components/geniushub/services.yaml index 7d4cd14b19e9c0..48b45a0811fa69 100644 --- a/homeassistant/components/geniushub/services.yaml +++ b/homeassistant/components/geniushub/services.yaml @@ -2,21 +2,14 @@ # Describes the format for available services set_zone_mode: - name: Set zone mode - description: >- - Set the zone to an operating mode. fields: entity_id: - name: Entity - description: The zone's entity_id. required: true selector: entity: integration: geniushub domain: climate mode: - name: Mode - description: "One of: off, timer or footprint." required: true selector: select: @@ -26,21 +19,14 @@ set_zone_mode: - "footprint" set_zone_override: - name: Set zone override - description: >- - Override the zone's set point for a given duration. fields: entity_id: - name: Entity - description: The zone's entity_id. required: true selector: entity: integration: geniushub domain: climate temperature: - name: Temperature - description: The target temperature. required: true selector: number: @@ -49,26 +35,17 @@ set_zone_override: step: 0.1 unit_of_measurement: "°" duration: - name: Duration - description: >- - The duration of the override. Optional, default 1 hour, maximum 24 hours. example: '{"minutes": 135}' selector: object: set_switch_override: - name: Set switch override - description: >- - Override switch for a given duration. target: entity: integration: geniushub domain: switch fields: duration: - name: Duration - description: >- - The duration of the override. Optional, default 1 hour, maximum 24 hours. example: '{"minutes": 135}' selector: object: diff --git a/homeassistant/components/geniushub/strings.json b/homeassistant/components/geniushub/strings.json new file mode 100644 index 00000000000000..1c1092ee256dd7 --- /dev/null +++ b/homeassistant/components/geniushub/strings.json @@ -0,0 +1,46 @@ +{ + "services": { + "set_zone_mode": { + "name": "Set zone mode", + "description": "Set the zone to an operating mode.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "The zone's entity_id." + }, + "mode": { + "name": "Mode", + "description": "One of: off, timer or footprint." + } + } + }, + "set_zone_override": { + "name": "Set zone override", + "description": "Overrides the zone's set point for a given duration.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "The zone's entity_id." + }, + "temperature": { + "name": "Temperature", + "description": "The target temperature." + }, + "duration": { + "name": "Duration", + "description": "The duration of the override. Optional, default 1 hour, maximum 24 hours." + } + } + }, + "set_switch_override": { + "name": "Set switch override", + "description": "Overrides switch for a given duration.", + "fields": { + "duration": { + "name": "Duration", + "description": "The duration of the override. Optional, default 1 hour, maximum 24 hours." + } + } + } + } +} diff --git a/homeassistant/components/google/services.yaml b/homeassistant/components/google/services.yaml index e7eeef7594755e..f715679dff8648 100644 --- a/homeassistant/components/google/services.yaml +++ b/homeassistant/components/google/services.yaml @@ -1,111 +1,75 @@ add_event: - name: Add event - description: Add a new calendar event. fields: calendar_id: - name: Calendar ID - description: The id of the calendar you want. required: true example: "Your email" selector: text: summary: - name: Summary - description: Acts as the title of the event. required: true example: "Bowling" selector: text: description: - name: Description - description: The description of the event. Optional. example: "Birthday bowling" selector: text: start_date_time: - name: Start time - description: The date and time the event should start. example: "2019-03-22 20:00:00" selector: text: end_date_time: - name: End time - description: The date and time the event should end. example: "2019-03-22 22:00:00" selector: text: start_date: - name: Start date - description: The date the whole day event should start. example: "2019-03-10" selector: text: end_date: - name: End date - description: The date the whole day event should end. example: "2019-03-11" selector: text: in: - name: In - description: Days or weeks that you want to create the event in. example: '"days": 2 or "weeks": 2' selector: object: create_event: - name: Create event - description: Add a new calendar event. target: entity: integration: google domain: calendar fields: summary: - name: Summary - description: Acts as the title of the event. required: true example: "Bowling" selector: text: description: - name: Description - description: The description of the event. Optional. example: "Birthday bowling" selector: text: start_date_time: - name: Start time - description: The date and time the event should start. example: "2022-03-22 20:00:00" selector: text: end_date_time: - name: End time - description: The date and time the event should end. example: "2022-03-22 22:00:00" selector: text: start_date: - name: Start date - description: The date the whole day event should start. example: "2022-03-10" selector: text: end_date: - name: End date - description: The date the whole day event should end. example: "2022-03-11" selector: text: in: - name: In - description: Days or weeks that you want to create the event in. example: '"days": 2 or "weeks": 2' selector: object: location: - name: Location - description: The location of the event. Optional. example: "Conference Room - F123, Bldg. 002" selector: text: diff --git a/homeassistant/components/google/strings.json b/homeassistant/components/google/strings.json index 5c9b642447367a..7fa1569992f6d8 100644 --- a/homeassistant/components/google/strings.json +++ b/homeassistant/components/google/strings.json @@ -42,5 +42,83 @@ }, "application_credentials": { "description": "Follow the [instructions]({more_info_url}) for [OAuth consent screen]({oauth_consent_url}) to give Home Assistant access to your Google Calendar. You also need to create Application Credentials linked to your Calendar:\n1. Go to [Credentials]({oauth_creds_url}) and click **Create Credentials**.\n1. From the drop-down list select **OAuth client ID**.\n1. Select **TV and Limited Input devices** for the Application Type.\n\n" + }, + "services": { + "add_event": { + "name": "Add event", + "description": "Adds a new calendar event.", + "fields": { + "calendar_id": { + "name": "Calendar ID", + "description": "The id of the calendar you want." + }, + "summary": { + "name": "Summary", + "description": "Acts as the title of the event." + }, + "description": { + "name": "Description", + "description": "The description of the event. Optional." + }, + "start_date_time": { + "name": "Start time", + "description": "The date and time the event should start." + }, + "end_date_time": { + "name": "End time", + "description": "The date and time the event should end." + }, + "start_date": { + "name": "Start date", + "description": "The date the whole day event should start." + }, + "end_date": { + "name": "End date", + "description": "The date the whole day event should end." + }, + "in": { + "name": "In", + "description": "Days or weeks that you want to create the event in." + } + } + }, + "create_event": { + "name": "Creates event", + "description": "Add a new calendar event.", + "fields": { + "summary": { + "name": "Summary", + "description": "Acts as the title of the event." + }, + "description": { + "name": "Description", + "description": "The description of the event. Optional." + }, + "start_date_time": { + "name": "Start time", + "description": "The date and time the event should start." + }, + "end_date_time": { + "name": "End time", + "description": "The date and time the event should end." + }, + "start_date": { + "name": "Start date", + "description": "The date the whole day event should start." + }, + "end_date": { + "name": "End date", + "description": "The date the whole day event should end." + }, + "in": { + "name": "In", + "description": "Days or weeks that you want to create the event in." + }, + "location": { + "name": "Location", + "description": "The location of the event. Optional." + } + } + } } } diff --git a/homeassistant/components/google_assistant/services.yaml b/homeassistant/components/google_assistant/services.yaml index fe5ef51c2ce9ca..321eae3b2e906f 100644 --- a/homeassistant/components/google_assistant/services.yaml +++ b/homeassistant/components/google_assistant/services.yaml @@ -1,9 +1,5 @@ request_sync: - name: Request sync - description: Send a request_sync command to Google. fields: agent_user_id: - name: Agent user ID - description: "Only needed for automations. Specific Home Assistant user id (not username, ID in configuration > users > under username) to sync with Google Assistant. Do not need when you call this service through Home Assistant front end or API. Used in automation script or other place where context.user_id is missing." selector: text: diff --git a/homeassistant/components/google_assistant/strings.json b/homeassistant/components/google_assistant/strings.json new file mode 100644 index 00000000000000..cb01a0febf5282 --- /dev/null +++ b/homeassistant/components/google_assistant/strings.json @@ -0,0 +1,14 @@ +{ + "services": { + "request_sync": { + "name": "Request sync", + "description": "Sends a request_sync command to Google.", + "fields": { + "agent_user_id": { + "name": "Agent user ID", + "description": "Only needed for automations. Specific Home Assistant user id (not username, ID in configuration > users > under username) to sync with Google Assistant. Do not need when you call this service through Home Assistant front end or API. Used in automation script or other place where context.user_id is missing." + } + } + } + } +} diff --git a/homeassistant/components/google_assistant_sdk/services.yaml b/homeassistant/components/google_assistant_sdk/services.yaml index fc2a3ad264f561..f8853ec93ea327 100644 --- a/homeassistant/components/google_assistant_sdk/services.yaml +++ b/homeassistant/components/google_assistant_sdk/services.yaml @@ -1,16 +1,10 @@ send_text_command: - name: Send text command - description: Send a command as a text query to Google Assistant. fields: command: - name: Command - description: Command(s) to send to Google Assistant. example: turn off kitchen TV selector: text: media_player: - name: Media Player Entity - description: Name(s) of media player entities to play response on example: media_player.living_room_speaker selector: entity: diff --git a/homeassistant/components/google_assistant_sdk/strings.json b/homeassistant/components/google_assistant_sdk/strings.json index 66a2b975b5e15a..e9e2b7d4c0932f 100644 --- a/homeassistant/components/google_assistant_sdk/strings.json +++ b/homeassistant/components/google_assistant_sdk/strings.json @@ -38,5 +38,21 @@ }, "application_credentials": { "description": "Follow the [instructions]({more_info_url}) for [OAuth consent screen]({oauth_consent_url}) to give Home Assistant access to your Google Assistant SDK. You also need to create Application Credentials linked to your account:\n1. Go to [Credentials]({oauth_creds_url}) and click **Create Credentials**.\n1. From the drop-down list select **OAuth client ID**.\n1. Select **Web application** for the Application Type.\n\n" + }, + "services": { + "send_text_command": { + "name": "Send text command", + "description": "Sends a command as a text query to Google Assistant.", + "fields": { + "command": { + "name": "Command", + "description": "Command(s) to send to Google Assistant." + }, + "media_player": { + "name": "Media player entity", + "description": "Name(s) of media player entities to play response on." + } + } + } } } diff --git a/homeassistant/components/google_mail/services.yaml b/homeassistant/components/google_mail/services.yaml index 76ef40fa3aa781..9ce1c41f27a3a5 100644 --- a/homeassistant/components/google_mail/services.yaml +++ b/homeassistant/components/google_mail/services.yaml @@ -1,6 +1,4 @@ set_vacation: - name: Set Vacation - description: Set vacation responder settings for Google Mail. target: device: integration: google_mail @@ -8,46 +6,30 @@ set_vacation: integration: google_mail fields: enabled: - name: Enabled required: true default: true - description: Turn this off to end vacation responses. selector: boolean: title: - name: Title - description: The subject for the email selector: text: message: - name: Message - description: Body of the email required: true selector: text: plain_text: - name: Plain text default: true - description: Choose to send message in plain text or HTML. selector: boolean: restrict_contacts: - name: Restrict to Contacts - description: Restrict automatic reply to contacts. selector: boolean: restrict_domain: - name: Restrict to Domain - description: Restrict automatic reply to domain. This only affects GSuite accounts. selector: boolean: start: - name: start - description: First day of the vacation selector: date: end: - name: end - description: Last day of the vacation selector: date: diff --git a/homeassistant/components/google_mail/strings.json b/homeassistant/components/google_mail/strings.json index 2f76806dfd351a..db242479783ad9 100644 --- a/homeassistant/components/google_mail/strings.json +++ b/homeassistant/components/google_mail/strings.json @@ -37,5 +37,45 @@ "name": "Vacation end date" } } + }, + "services": { + "set_vacation": { + "name": "Set vacation", + "description": "Sets vacation responder settings for Google Mail.", + "fields": { + "enabled": { + "name": "Enabled", + "description": "Turn this off to end vacation responses." + }, + "title": { + "name": "Title", + "description": "The subject for the email." + }, + "message": { + "name": "Message", + "description": "Body of the email." + }, + "plain_text": { + "name": "Plain text", + "description": "Choose to send message in plain text or HTML." + }, + "restrict_contacts": { + "name": "Restrict to contacts", + "description": "Restrict automatic reply to contacts." + }, + "restrict_domain": { + "name": "Restrict to domain", + "description": "Restrict automatic reply to domain. This only affects GSuite accounts." + }, + "start": { + "name": "Start", + "description": "First day of the vacation." + }, + "end": { + "name": "End", + "description": "Last day of the vacation." + } + } + } } } diff --git a/homeassistant/components/google_sheets/services.yaml b/homeassistant/components/google_sheets/services.yaml index 7524ba50fb5aa0..169352d1bac163 100644 --- a/homeassistant/components/google_sheets/services.yaml +++ b/homeassistant/components/google_sheets/services.yaml @@ -1,23 +1,15 @@ append_sheet: - name: Append to Sheet - description: Append data to a worksheet in Google Sheets. fields: config_entry: - name: Sheet - description: The sheet to add data to required: true selector: config_entry: integration: google_sheets worksheet: - name: Worksheet - description: Name of the worksheet. Defaults to the first one in the document. example: "Sheet1" selector: text: data: - name: Data - description: Data to be appended to the worksheet. This puts the values on a new row underneath the matching column (key). Any new key is placed on the top of a new column. required: true example: '{"hello": world, "cool": True, "count": 5}' selector: diff --git a/homeassistant/components/google_sheets/strings.json b/homeassistant/components/google_sheets/strings.json index 602301758f8b8b..b2cba19031ee50 100644 --- a/homeassistant/components/google_sheets/strings.json +++ b/homeassistant/components/google_sheets/strings.json @@ -31,5 +31,25 @@ }, "application_credentials": { "description": "Follow the [instructions]({more_info_url}) for [OAuth consent screen]({oauth_consent_url}) to give Home Assistant access to your Google Sheets. You also need to create Application Credentials linked to your account:\n1. Go to [Credentials]({oauth_creds_url}) and click **Create Credentials**.\n1. From the drop-down list select **OAuth client ID**.\n1. Select **Web application** for the Application Type.\n\n" + }, + "services": { + "append_sheet": { + "name": "Append to sheet", + "description": "Appends data to a worksheet in Google Sheets.", + "fields": { + "config_entry": { + "name": "Sheet", + "description": "The sheet to add data to." + }, + "worksheet": { + "name": "Worksheet", + "description": "Name of the worksheet. Defaults to the first one in the document." + }, + "data": { + "name": "Data", + "description": "Data to be appended to the worksheet. This puts the values on a new row underneath the matching column (key). Any new key is placed on the top of a new column." + } + } + } } } diff --git a/homeassistant/components/guardian/services.yaml b/homeassistant/components/guardian/services.yaml index 7415ac626a9247..c8f2414a87bbc9 100644 --- a/homeassistant/components/guardian/services.yaml +++ b/homeassistant/components/guardian/services.yaml @@ -1,68 +1,46 @@ # Describes the format for available Elexa Guardians services pair_sensor: - name: Pair Sensor - description: Add a new paired sensor to the valve controller. fields: device_id: - name: Valve Controller - description: The valve controller to add the sensor to required: true selector: device: integration: guardian uid: - name: UID - description: The UID of the paired sensor required: true example: 5410EC688BCF selector: text: unpair_sensor: - name: Unpair Sensor - description: Remove a paired sensor from the valve controller. fields: device_id: - name: Valve Controller - description: The valve controller to remove the sensor from required: true selector: device: integration: guardian uid: - name: UID - description: The UID of the paired sensor required: true example: 5410EC688BCF selector: text: upgrade_firmware: - name: Upgrade firmware - description: Upgrade the device firmware. fields: device_id: - name: Valve Controller - description: The valve controller whose firmware should be upgraded required: true selector: device: integration: guardian url: - name: URL - description: The URL of the server hosting the firmware file. example: https://repo.guardiancloud.services/gvc/fw selector: text: port: - name: Port - description: The port on which the firmware file is served. example: 443 selector: number: min: 1 max: 65535 filename: - name: Filename - description: The firmware filename. example: latest.bin selector: text: diff --git a/homeassistant/components/guardian/strings.json b/homeassistant/components/guardian/strings.json index ec2ad8d77cca71..f416adac027a01 100644 --- a/homeassistant/components/guardian/strings.json +++ b/homeassistant/components/guardian/strings.json @@ -45,5 +45,57 @@ "name": "Valve controller" } } + }, + "services": { + "pair_sensor": { + "name": "Pair sensor", + "description": "Adds a new paired sensor to the valve controller.", + "fields": { + "device_id": { + "name": "Valve controller", + "description": "The valve controller to add the sensor to." + }, + "uid": { + "name": "UID", + "description": "The UID of the paired sensor." + } + } + }, + "unpair_sensor": { + "name": "Unpair sensor", + "description": "Removes a paired sensor from the valve controller.", + "fields": { + "device_id": { + "name": "Valve controller", + "description": "The valve controller to remove the sensor from." + }, + "uid": { + "name": "UID", + "description": "The UID of the paired sensor." + } + } + }, + "upgrade_firmware": { + "name": "Upgrade firmware", + "description": "Upgrades the device firmware.", + "fields": { + "device_id": { + "name": "Valve controller", + "description": "The valve controller whose firmware should be upgraded." + }, + "url": { + "name": "URL", + "description": "The URL of the server hosting the firmware file." + }, + "port": { + "name": "Port", + "description": "The port on which the firmware file is served." + }, + "filename": { + "name": "Filename", + "description": "The firmware filename." + } + } + } } } diff --git a/homeassistant/components/habitica/services.yaml b/homeassistant/components/habitica/services.yaml index e60e2238088196..a7ef39eb5299f6 100644 --- a/homeassistant/components/habitica/services.yaml +++ b/homeassistant/components/habitica/services.yaml @@ -1,25 +1,17 @@ # Describes the format for Habitica service api_call: - name: API name - description: Call Habitica API fields: name: - name: Name - description: Habitica's username to call for required: true example: "xxxNotAValidNickxxx" selector: text: path: - name: Path - description: "Items from API URL in form of an array with method attached at the end. Consult https://habitica.com/apidoc/. Example uses https://habitica.com/apidoc/#api-Task-CreateUserTasks" required: true example: '["tasks", "user", "post"]' selector: object: args: - name: Args - description: Any additional JSON or URL parameter arguments. See apidoc mentioned for path. Example uses same API endpoint example: '{"text": "Use API from Home Assistant", "type": "todo"}' selector: object: diff --git a/homeassistant/components/habitica/strings.json b/homeassistant/components/habitica/strings.json index 3fe73d8466777b..8d2fb38517d977 100644 --- a/homeassistant/components/habitica/strings.json +++ b/homeassistant/components/habitica/strings.json @@ -11,12 +11,32 @@ "user": { "data": { "url": "[%key:common::config_flow::data::url%]", - "name": "Override for Habitica’s username. Will be used for service calls", - "api_user": "Habitica’s API user ID", + "name": "Override for Habitica\u2019s username. Will be used for service calls", + "api_user": "Habitica\u2019s API user ID", "api_key": "[%key:common::config_flow::data::api_key%]" }, "description": "Connect your Habitica profile to allow monitoring of your user's profile and tasks. Note that api_id and api_key must be gotten from https://habitica.com/user/settings/api" } } + }, + "services": { + "api_call": { + "name": "API name", + "description": "Calls Habitica API.", + "fields": { + "name": { + "name": "Name", + "description": "Habitica's username to call for." + }, + "path": { + "name": "Path", + "description": "Items from API URL in form of an array with method attached at the end. Consult https://habitica.com/apidoc/. Example uses https://habitica.com/apidoc/#api-Task-CreateUserTasks." + }, + "args": { + "name": "Args", + "description": "Any additional JSON or URL parameter arguments. See apidoc mentioned for path. Example uses same API endpoint." + } + } + } } } diff --git a/homeassistant/components/harmony/services.yaml b/homeassistant/components/harmony/services.yaml index fd53912397a3fc..be2a3178a8b7ff 100644 --- a/homeassistant/components/harmony/services.yaml +++ b/homeassistant/components/harmony/services.yaml @@ -1,22 +1,16 @@ sync: - name: Sync - description: Syncs the remote's configuration. target: entity: integration: harmony domain: remote change_channel: - name: Change channel - description: Sends change channel command to the Harmony HUB target: entity: integration: harmony domain: remote fields: channel: - name: Channel - description: Channel number to change to required: true selector: number: diff --git a/homeassistant/components/harmony/strings.json b/homeassistant/components/harmony/strings.json index 62de202372b7bf..8e2b435483f4e2 100644 --- a/homeassistant/components/harmony/strings.json +++ b/homeassistant/components/harmony/strings.json @@ -41,5 +41,21 @@ } } } + }, + "services": { + "sync": { + "name": "Sync", + "description": "Syncs the remote's configuration." + }, + "change_channel": { + "name": "Change channel", + "description": "Sends change channel command to the Harmony HUB.", + "fields": { + "channel": { + "name": "Channel", + "description": "Channel number to change to." + } + } + } } } diff --git a/homeassistant/components/hdmi_cec/services.yaml b/homeassistant/components/hdmi_cec/services.yaml index 7ad8b36473f859..e4102c44208329 100644 --- a/homeassistant/components/hdmi_cec/services.yaml +++ b/homeassistant/components/hdmi_cec/services.yaml @@ -1,74 +1,43 @@ power_on: - name: Power on - description: Power on all devices which supports it. select_device: - name: Select device - description: Select HDMI device. fields: device: - name: Device - description: Address of device to select. Can be entity_id, physical address or alias from configuration. required: true example: '"switch.hdmi_1" or "1.1.0.0" or "01:10"' selector: text: send_command: - name: Send command - description: Sends CEC command into HDMI CEC capable adapter. fields: att: - name: Att - description: Optional parameters. example: [0, 2] selector: object: cmd: - name: Command - description: 'Command itself. Could be decimal number or string with hexadeximal notation: "0x10".' example: 144 or "0x90" selector: text: dst: - name: Destination - description: 'Destination for command. Could be decimal number or string with hexadeximal notation: "0x10".' example: 5 or "0x5" selector: text: raw: - name: Raw - description: >- - Raw CEC command in format "00:00:00:00" where first two digits - are source and destination, second byte is command and optional other bytes - are command parameters. If raw command specified, other params are ignored. example: '"10:36"' selector: text: src: - name: Source - description: 'Source of command. Could be decimal number or string with hexadeximal notation: "0x10".' example: 12 or "0xc" selector: text: standby: - name: Standby - description: Standby all devices which supports it. update: - name: Update - description: Update devices state from network. volume: - name: Volume - description: Increase or decrease volume of system. fields: down: - name: Down - description: Decreases volume x levels. selector: number: min: 1 max: 100 mute: - name: Mute - description: Mutes audio system. selector: select: options: @@ -76,8 +45,6 @@ volume: - "on" - "toggle" up: - name: Up - description: Increases volume x levels. selector: number: min: 1 diff --git a/homeassistant/components/hdmi_cec/strings.json b/homeassistant/components/hdmi_cec/strings.json new file mode 100644 index 00000000000000..6efc9ec4272cb7 --- /dev/null +++ b/homeassistant/components/hdmi_cec/strings.json @@ -0,0 +1,70 @@ +{ + "services": { + "power_on": { + "name": "Power on", + "description": "Power on all devices which supports it." + }, + "select_device": { + "name": "Select device", + "description": "Select HDMI device.", + "fields": { + "device": { + "name": "Device", + "description": "Address of device to select. Can be entity_id, physical address or alias from configuration." + } + } + }, + "send_command": { + "name": "Send command", + "description": "Sends CEC command into HDMI CEC capable adapter.", + "fields": { + "att": { + "name": "Att", + "description": "Optional parameters." + }, + "cmd": { + "name": "Command", + "description": "Command itself. Could be decimal number or string with hexadeximal notation: \"0x10\"." + }, + "dst": { + "name": "Destination", + "description": "Destination for command. Could be decimal number or string with hexadeximal notation: \"0x10\"." + }, + "raw": { + "name": "Raw", + "description": "Raw CEC command in format \"00:00:00:00\" where first two digits are source and destination, second byte is command and optional other bytes are command parameters. If raw command specified, other params are ignored." + }, + "src": { + "name": "Source", + "description": "Source of command. Could be decimal number or string with hexadeximal notation: \"0x10\"." + } + } + }, + "standby": { + "name": "Standby", + "description": "Standby all devices which supports it." + }, + "update": { + "name": "Update", + "description": "Updates devices state from network." + }, + "volume": { + "name": "Volume", + "description": "Increases or decreases volume of system.", + "fields": { + "down": { + "name": "Down", + "description": "Decreases volume x levels." + }, + "mute": { + "name": "Mute", + "description": "Mutes audio system." + }, + "up": { + "name": "Up", + "description": "Increases volume x levels." + } + } + } + } +} diff --git a/homeassistant/components/heos/services.yaml b/homeassistant/components/heos/services.yaml index 320ed297873c9e..8dc222d65baf22 100644 --- a/homeassistant/components/heos/services.yaml +++ b/homeassistant/components/heos/services.yaml @@ -1,22 +1,14 @@ sign_in: - name: Sign in - description: Sign the controller in to a HEOS account. fields: username: - name: Username - description: The username or email of the HEOS account. required: true example: "example@example.com" selector: text: password: - name: Password - description: The password of the HEOS account. required: true example: "password" selector: text: sign_out: - name: Sign out - description: Sign the controller out of the HEOS account. diff --git a/homeassistant/components/heos/strings.json b/homeassistant/components/heos/strings.json index 09ada292afde62..635fe08cccc4c0 100644 --- a/homeassistant/components/heos/strings.json +++ b/homeassistant/components/heos/strings.json @@ -15,5 +15,25 @@ "abort": { "single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]" } + }, + "services": { + "sign_in": { + "name": "Sign in", + "description": "Signs the controller in to a HEOS account.", + "fields": { + "username": { + "name": "Username", + "description": "The username or email of the HEOS account." + }, + "password": { + "name": "Password", + "description": "The password of the HEOS account." + } + } + }, + "sign_out": { + "name": "Sign out", + "description": "Signs the controller out of the HEOS account." + } } } diff --git a/homeassistant/components/hive/services.yaml b/homeassistant/components/hive/services.yaml index d0de9645c6a152..9606624623028d 100644 --- a/homeassistant/components/hive/services.yaml +++ b/homeassistant/components/hive/services.yaml @@ -1,21 +1,15 @@ boost_heating: - name: Boost Heating (To be deprecated) - description: To be deprecated please use boost_heating_on. target: entity: integration: hive domain: climate fields: time_period: - name: Time Period - description: Set the time period for the boost. required: true example: 01:30:00 selector: time: temperature: - name: Temperature - description: Set the target temperature for the boost period. default: 25.0 selector: number: @@ -24,23 +18,17 @@ boost_heating: step: 0.5 unit_of_measurement: ° boost_heating_on: - name: Boost Heating On - description: Set the boost mode ON defining the period of time and the desired target temperature for the boost. target: entity: integration: hive domain: climate fields: time_period: - name: Time Period - description: Set the time period for the boost. required: true example: 01:30:00 selector: time: temperature: - name: Temperature - description: Set the target temperature for the boost period. default: 25.0 selector: number: @@ -49,39 +37,27 @@ boost_heating_on: step: 0.5 unit_of_measurement: ° boost_heating_off: - name: Boost Heating Off - description: Set the boost mode OFF. fields: entity_id: - name: Entity ID - description: Select entity_id to turn boost off. required: true selector: entity: integration: hive domain: climate boost_hot_water: - name: Boost Hotwater - description: Set the boost mode ON or OFF defining the period of time for the boost. fields: entity_id: - name: Entity ID - description: Select entity_id to boost. required: true selector: entity: integration: hive domain: water_heater time_period: - name: Time Period - description: Set the time period for the boost. required: true example: 01:30:00 selector: time: on_off: - name: Mode - description: Set the boost function on or off. required: true selector: select: diff --git a/homeassistant/components/hive/strings.json b/homeassistant/components/hive/strings.json index 3435517aec70bc..495c5dad1cc133 100644 --- a/homeassistant/components/hive/strings.json +++ b/homeassistant/components/hive/strings.json @@ -56,5 +56,63 @@ } } } + }, + "services": { + "boost_heating": { + "name": "Boost heating (to be deprecated)", + "description": "To be deprecated please use boost_heating_on.", + "fields": { + "time_period": { + "name": "Time period", + "description": "Set the time period for the boost." + }, + "temperature": { + "name": "Temperature", + "description": "Set the target temperature for the boost period." + } + } + }, + "boost_heating_on": { + "name": "Boost heating on", + "description": "Sets the boost mode ON defining the period of time and the desired target temperature for the boost.", + "fields": { + "time_period": { + "name": "Time Period", + "description": "Set the time period for the boost." + }, + "temperature": { + "name": "Temperature", + "description": "Set the target temperature for the boost period." + } + } + }, + "boost_heating_off": { + "name": "Boost heating off", + "description": "Sets the boost mode OFF.", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Select entity_id to turn boost off." + } + } + }, + "boost_hot_water": { + "name": "Boost hotwater", + "description": "Sets the boost mode ON or OFF defining the period of time for the boost.", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Select entity_id to boost." + }, + "time_period": { + "name": "Time period", + "description": "Set the time period for the boost." + }, + "on_off": { + "name": "Mode", + "description": "Set the boost function on or off." + } + } + } } } diff --git a/homeassistant/components/home_connect/services.yaml b/homeassistant/components/home_connect/services.yaml index 06a646dd481460..0738b58595a76a 100644 --- a/homeassistant/components/home_connect/services.yaml +++ b/homeassistant/components/home_connect/services.yaml @@ -1,168 +1,112 @@ start_program: - name: Start program - description: Selects a program and starts it. fields: device_id: - name: Device ID - description: Id of the device. required: true selector: device: integration: home_connect program: - name: Program - description: Program to select example: "Dishcare.Dishwasher.Program.Auto2" required: true selector: text: key: - name: Option key - description: Key of the option. example: "BSH.Common.Option.StartInRelative" selector: text: value: - name: Option value - description: Value of the option. example: 1800 selector: object: unit: - name: Option unit - description: Unit for the option. example: "seconds" selector: text: select_program: - name: Select program - description: Selects a program without starting it. fields: device_id: - name: Device ID - description: Id of the device. required: true selector: device: integration: home_connect program: - name: Program - description: Program to select example: "Dishcare.Dishwasher.Program.Auto2" required: true selector: text: key: - name: Option key - description: Key of the option. example: "BSH.Common.Option.StartInRelative" selector: text: value: - name: Option value - description: Value of the option. example: 1800 selector: object: unit: - name: Option unit - description: Unit for the option. example: "seconds" selector: text: pause_program: - name: Pause program - description: Pauses the current running program. fields: device_id: - name: Device ID - description: Id of the device. required: true selector: device: integration: home_connect resume_program: - name: Resume program - description: Resumes a paused program. fields: device_id: - name: Device ID - description: Id of the device. required: true selector: device: integration: home_connect set_option_active: - name: Set active program option - description: Sets an option for the active program. fields: device_id: - name: Device ID - description: Id of the device. required: true selector: device: integration: home_connect key: - name: Key - description: Key of the option. example: "LaundryCare.Dryer.Option.DryingTarget" required: true selector: text: value: - name: Value - description: Value of the option. example: "LaundryCare.Dryer.EnumType.DryingTarget.IronDry" required: true selector: object: set_option_selected: - name: Set selected program option - description: Sets an option for the selected program. fields: device_id: - name: Device ID - description: Id of the device. required: true selector: device: integration: home_connect key: - name: Key - description: Key of the option. example: "LaundryCare.Dryer.Option.DryingTarget" required: true selector: text: value: - name: Value - description: Value of the option. example: "LaundryCare.Dryer.EnumType.DryingTarget.IronDry" required: true selector: object: change_setting: - name: Change setting - description: Changes a setting. fields: device_id: - name: Device ID - description: Id of the device. required: true selector: device: integration: home_connect key: - name: Key - description: Key of the setting. example: "BSH.Common.Setting.ChildLock" required: true selector: text: value: - name: Value - description: Value of the setting. example: "true" required: true selector: diff --git a/homeassistant/components/home_connect/strings.json b/homeassistant/components/home_connect/strings.json index 79455783edf7e9..41eedbe83a87d8 100644 --- a/homeassistant/components/home_connect/strings.json +++ b/homeassistant/components/home_connect/strings.json @@ -12,5 +12,133 @@ "create_entry": { "default": "[%key:common::config_flow::create_entry::authenticated%]" } + }, + "services": { + "start_program": { + "name": "Start program", + "description": "Selects a program and starts it.", + "fields": { + "device_id": { + "name": "Device ID", + "description": "Id of the device." + }, + "program": { + "name": "Program", + "description": "Program to select." + }, + "key": { + "name": "Option key", + "description": "Key of the option." + }, + "value": { + "name": "Option value", + "description": "Value of the option." + }, + "unit": { + "name": "Option unit", + "description": "Unit for the option." + } + } + }, + "select_program": { + "name": "Select program", + "description": "Selects a program without starting it.", + "fields": { + "device_id": { + "name": "Device ID", + "description": "Id of the device." + }, + "program": { + "name": "Program", + "description": "Program to select." + }, + "key": { + "name": "Option key", + "description": "Key of the option." + }, + "value": { + "name": "Option value", + "description": "Value of the option." + }, + "unit": { + "name": "Option unit", + "description": "Unit for the option." + } + } + }, + "pause_program": { + "name": "Pause program", + "description": "Pauses the current running program.", + "fields": { + "device_id": { + "name": "Device ID", + "description": "Id of the device." + } + } + }, + "resume_program": { + "name": "Resume program", + "description": "Resumes a paused program.", + "fields": { + "device_id": { + "name": "Device ID", + "description": "Id of the device." + } + } + }, + "set_option_active": { + "name": "Set active program option", + "description": "Sets an option for the active program.", + "fields": { + "device_id": { + "name": "Device ID", + "description": "Id of the device." + }, + "key": { + "name": "Key", + "description": "Key of the option." + }, + "value": { + "name": "Value", + "description": "Value of the option." + } + } + }, + "set_option_selected": { + "name": "Set selected program option", + "description": "Sets an option for the selected program.", + "fields": { + "device_id": { + "name": "Device ID", + "description": "Id of the device." + }, + "key": { + "name": "Key", + "description": "Key of the option." + }, + "value": { + "name": "Value", + "description": "Value of the option." + } + } + }, + "change_setting": { + "name": "Change setting", + "description": "Changes a setting.", + "fields": { + "device_id": { + "name": "Device ID", + "description": "Id of the device." + }, + "key": { + "name": "Key", + "description": "Key of the setting." + }, + "value": { + "name": "Value", + "description": "Value of the setting." + } + } + } } } diff --git a/homeassistant/components/homekit/services.yaml b/homeassistant/components/homekit/services.yaml index a982e9ccf8d5e8..de271db0ad9c70 100644 --- a/homeassistant/components/homekit/services.yaml +++ b/homeassistant/components/homekit/services.yaml @@ -1,18 +1,11 @@ # Describes the format for available HomeKit services reload: - name: Reload - description: Reload homekit and re-process YAML configuration - reset_accessory: - name: Reset accessory - description: Reset a HomeKit accessory target: entity: {} unpair: - name: Unpair an accessory or bridge - description: Forcefully remove all pairings from an accessory to allow re-pairing. Use this service if the accessory is no longer responsive, and you want to avoid deleting and re-adding the entry. Room locations, and accessory preferences will be lost. target: device: integration: homekit diff --git a/homeassistant/components/homekit/strings.json b/homeassistant/components/homekit/strings.json index 74af388df85659..83177345159690 100644 --- a/homeassistant/components/homekit/strings.json +++ b/homeassistant/components/homekit/strings.json @@ -24,14 +24,14 @@ "data": { "entities": "Entities" }, - "description": "Select entities from each domain in “{domains}”. The include will cover the entire domain if you do not select any entities for a given domain.", + "description": "Select entities from each domain in \u201c{domains}\u201d. The include will cover the entire domain if you do not select any entities for a given domain.", "title": "Select the entities to be included" }, "exclude": { "data": { "entities": "[%key:component::homekit::options::step::include::data::entities%]" }, - "description": "All “{domains}” entities will be included except for the excluded entities and categorized entities.", + "description": "All \u201c{domains}\u201d entities will be included except for the excluded entities and categorized entities.", "title": "Select the entities to be excluded" }, "cameras": { @@ -68,5 +68,19 @@ "abort": { "port_name_in_use": "An accessory or bridge with the same name or port is already configured." } + }, + "services": { + "reload": { + "name": "Reload", + "description": "Reloads homekit and re-process YAML-configuration." + }, + "reset_accessory": { + "name": "Reset accessory", + "description": "Resets a HomeKit accessory." + }, + "unpair": { + "name": "Unpair an accessory or bridge", + "description": "Forcefully removes all pairings from an accessory to allow re-pairing. Use this service if the accessory is no longer responsive, and you want to avoid deleting and re-adding the entry. Room locations, and accessory preferences will be lost." + } } } diff --git a/homeassistant/components/homematic/services.yaml b/homeassistant/components/homematic/services.yaml index 28b6577cdf9dfb..529079666883e6 100644 --- a/homeassistant/components/homematic/services.yaml +++ b/homeassistant/components/homematic/services.yaml @@ -1,105 +1,73 @@ # Describes the format for available component services virtualkey: - name: Virtual key - description: Press a virtual key from CCU/Homegear or simulate keypress. fields: address: - name: Address - description: Address of homematic device or BidCoS-RF for virtual remote. required: true example: BidCoS-RF selector: text: channel: - name: Channel - description: Channel for calling a keypress. required: true selector: number: min: 1 max: 6 param: - name: Param - description: Event to send i.e. PRESS_LONG, PRESS_SHORT. required: true example: PRESS_LONG selector: text: interface: - name: Interface - description: Set an interface value. example: Interfaces name from config selector: text: set_variable_value: - name: Set variable value - description: Set the name of a node. fields: entity_id: - name: Entity - description: Name(s) of homematic central to set value. selector: entity: domain: homematic name: - name: Name - description: Name of the variable to set. required: true example: "testvariable" selector: text: value: - name: Value - description: New value required: true example: 1 selector: text: set_device_value: - name: Set device value - description: Set a device property on RPC XML interface. fields: address: - name: Address - description: Address of homematic device or BidCoS-RF for virtual remote required: true example: BidCoS-RF selector: text: channel: - name: Channel - description: Channel for calling a keypress required: true selector: number: min: 1 max: 6 param: - name: Param - description: Event to send i.e. PRESS_LONG, PRESS_SHORT required: true example: PRESS_LONG selector: text: interface: - name: Interface - description: Set an interface value example: Interfaces name from config selector: text: value: - name: Value - description: New value required: true example: 1 selector: text: value_type: - name: Value type - description: Type for new value selector: select: options: @@ -110,31 +78,20 @@ set_device_value: - "string" reconnect: - name: Reconnect - description: Reconnect to all Homematic Hubs. - set_install_mode: - name: Set install mode - description: Set a RPC XML interface into installation mode. fields: interface: - name: Interface - description: Select the given interface into install mode required: true example: Interfaces name from config selector: text: mode: - name: Mode - description: 1= Normal mode / 2= Remove exists old links default: 1 selector: number: min: 1 max: 2 time: - name: Time - description: Time to run in install mode default: 60 selector: number: @@ -142,47 +99,33 @@ set_install_mode: max: 3600 unit_of_measurement: seconds address: - name: Address - description: Address of homematic device or BidCoS-RF to learn example: LEQ3948571 selector: text: put_paramset: - name: Put paramset - description: Call to putParamset in the RPC XML interface fields: interface: - name: Interface - description: The interfaces name from the config required: true example: wireless selector: text: address: - name: Address - description: Address of Homematic device required: true example: LEQ3948571:0 selector: text: paramset_key: - name: Paramset key - description: The paramset_key argument to putParamset required: true example: MASTER selector: text: paramset: - name: Paramset - description: A paramset dictionary required: true example: '{"WEEK_PROGRAM_POINTER": 1}' selector: object: rx_mode: - name: RX mode - description: The receive mode used. example: BURST selector: text: diff --git a/homeassistant/components/homematic/strings.json b/homeassistant/components/homematic/strings.json new file mode 100644 index 00000000000000..14f723694fca6c --- /dev/null +++ b/homeassistant/components/homematic/strings.json @@ -0,0 +1,126 @@ +{ + "services": { + "virtualkey": { + "name": "Virtual key", + "description": "Presses a virtual key from CCU/Homegear or simulate keypress.", + "fields": { + "address": { + "name": "Address", + "description": "Address of homematic device or BidCoS-RF for virtual remote." + }, + "channel": { + "name": "Channel", + "description": "Channel for calling a keypress." + }, + "param": { + "name": "Param", + "description": "Event to send i.e. PRESS_LONG, PRESS_SHORT." + }, + "interface": { + "name": "Interface", + "description": "Set an interface value." + } + } + }, + "set_variable_value": { + "name": "Set variable value", + "description": "Sets the name of a node.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name(s) of homematic central to set value." + }, + "name": { + "name": "Name", + "description": "Name of the variable to set." + }, + "value": { + "name": "Value", + "description": "New value." + } + } + }, + "set_device_value": { + "name": "Set device value", + "description": "Sets a device property on RPC XML interface.", + "fields": { + "address": { + "name": "Address", + "description": "Address of homematic device or BidCoS-RF for virtual remote." + }, + "channel": { + "name": "Channel", + "description": "Channel for calling a keypress." + }, + "param": { + "name": "Param", + "description": "Event to send i.e. PRESS_LONG, PRESS_SHORT." + }, + "interface": { + "name": "Interface", + "description": "Set an interface value." + }, + "value": { + "name": "Value", + "description": "New value." + }, + "value_type": { + "name": "Value type", + "description": "Type for new value." + } + } + }, + "reconnect": { + "name": "Reconnect", + "description": "Reconnects to all Homematic Hubs." + }, + "set_install_mode": { + "name": "Set install mode", + "description": "Set a RPC XML interface into installation mode.", + "fields": { + "interface": { + "name": "Interface", + "description": "Select the given interface into install mode." + }, + "mode": { + "name": "Mode", + "description": "1= Normal mode / 2= Remove exists old links." + }, + "time": { + "name": "Time", + "description": "Time to run in install mode." + }, + "address": { + "name": "Address", + "description": "Address of homematic device or BidCoS-RF to learn." + } + } + }, + "put_paramset": { + "name": "Put paramset", + "description": "Calls to putParamset in the RPC XML interface.", + "fields": { + "interface": { + "name": "Interface", + "description": "The interfaces name from the config." + }, + "address": { + "name": "Address", + "description": "Address of Homematic device." + }, + "paramset_key": { + "name": "Paramset key", + "description": "The paramset_key argument to putParamset." + }, + "paramset": { + "name": "Paramset", + "description": "A paramset dictionary." + }, + "rx_mode": { + "name": "RX mode", + "description": "The receive mode used." + } + } + } + } +} diff --git a/homeassistant/components/homematicip_cloud/services.yaml b/homeassistant/components/homematicip_cloud/services.yaml index ebb83a0845f5d3..9e8313397877f2 100644 --- a/homeassistant/components/homematicip_cloud/services.yaml +++ b/homeassistant/components/homematicip_cloud/services.yaml @@ -1,12 +1,8 @@ # Describes the format for available component services activate_eco_mode_with_duration: - name: Activate eco mode with duration - description: Activate eco mode with period. fields: duration: - name: Duration - description: The duration of eco mode in minutes. required: true selector: number: @@ -14,44 +10,30 @@ activate_eco_mode_with_duration: max: 1440 unit_of_measurement: "minutes" accesspoint_id: - name: Accesspoint ID - description: The ID of the Homematic IP Access Point example: 3014xxxxxxxxxxxxxxxxxxxx selector: text: activate_eco_mode_with_period: - name: Activate eco more with period - description: Activate eco mode with period. fields: endtime: - name: Endtime - description: The time when the eco mode should automatically be disabled. required: true example: 2019-02-17 14:00 selector: text: accesspoint_id: - name: Accesspoint ID - description: The ID of the Homematic IP Access Point example: 3014xxxxxxxxxxxxxxxxxxxx selector: text: activate_vacation: - name: Activate vacation - description: Activates the vacation mode until the given time. fields: endtime: - name: Endtime - description: The time when the vacation mode should automatically be disabled. required: true example: 2019-09-17 14:00 selector: text: temperature: - name: Temperature - description: the set temperature during the vacation mode. required: true default: 18 selector: @@ -61,48 +43,32 @@ activate_vacation: step: 0.5 unit_of_measurement: "°" accesspoint_id: - name: Accesspoint ID - description: The ID of the Homematic IP Access Point example: 3014xxxxxxxxxxxxxxxxxxxx selector: text: deactivate_eco_mode: - name: Deactivate eco mode - description: Deactivates the eco mode immediately. fields: accesspoint_id: - name: Accesspoint ID - description: The ID of the Homematic IP Access Point example: 3014xxxxxxxxxxxxxxxxxxxx selector: text: deactivate_vacation: - name: Deactivate vacation - description: Deactivates the vacation mode immediately. fields: accesspoint_id: - name: Accesspoint ID - description: The ID of the Homematic IP Access Point example: 3014xxxxxxxxxxxxxxxxxxxx selector: text: set_active_climate_profile: - name: Set active climate profile - description: Set the active climate profile index. fields: entity_id: - name: Entity - description: The ID of the climate entity. Use 'all' keyword to switch the profile for all entities. required: true example: climate.livingroom selector: text: climate_profile_index: - name: Climate profile index - description: The index of the climate profile. required: true selector: number: @@ -110,36 +76,24 @@ set_active_climate_profile: max: 100 dump_hap_config: - name: Dump hap config - description: Dump the configuration of the Homematic IP Access Point(s). fields: config_output_path: - name: Config output path - description: (Default is 'Your home-assistant config directory') Path where to store the config. example: "/config" selector: text: config_output_file_prefix: - name: Config output file prefix - description: Name of the config file. The SGTIN of the AP will always be appended. example: "hmip-config" default: "hmip-config" selector: text: anonymize: - name: Anonymize - description: Should the Configuration be anonymized? default: true selector: boolean: reset_energy_counter: - name: Reset energy counter - description: Reset the energy counter of a measuring entity. fields: entity_id: - name: Entity - description: The ID of the measuring entity. Use 'all' keyword to reset all energy counters. required: true example: switch.livingroom selector: diff --git a/homeassistant/components/homematicip_cloud/strings.json b/homeassistant/components/homematicip_cloud/strings.json index 3e3c967f972f20..6a20c5f8a54293 100644 --- a/homeassistant/components/homematicip_cloud/strings.json +++ b/homeassistant/components/homematicip_cloud/strings.json @@ -25,5 +25,115 @@ "connection_aborted": "[%key:common::config_flow::error::cannot_connect%]", "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" } + }, + "services": { + "activate_eco_mode_with_duration": { + "name": "Activate eco mode with duration", + "description": "Activates eco mode with period.", + "fields": { + "duration": { + "name": "Duration", + "description": "The duration of eco mode in minutes." + }, + "accesspoint_id": { + "name": "Accesspoint ID", + "description": "The ID of the Homematic IP Access Point." + } + } + }, + "activate_eco_mode_with_period": { + "name": "Activate eco more with period", + "description": "Activates eco mode with period.", + "fields": { + "endtime": { + "name": "Endtime", + "description": "The time when the eco mode should automatically be disabled." + }, + "accesspoint_id": { + "name": "Accesspoint ID", + "description": "The ID of the Homematic IP Access Point." + } + } + }, + "activate_vacation": { + "name": "Activate vacation", + "description": "Activates the vacation mode until the given time.", + "fields": { + "endtime": { + "name": "Endtime", + "description": "The time when the vacation mode should automatically be disabled." + }, + "temperature": { + "name": "Temperature", + "description": "The set temperature during the vacation mode." + }, + "accesspoint_id": { + "name": "Accesspoint ID", + "description": "The ID of the Homematic IP Access Point." + } + } + }, + "deactivate_eco_mode": { + "name": "Deactivate eco mode", + "description": "Deactivates the eco mode immediately.", + "fields": { + "accesspoint_id": { + "name": "Accesspoint ID", + "description": "The ID of the Homematic IP Access Point." + } + } + }, + "deactivate_vacation": { + "name": "Deactivate vacation", + "description": "Deactivates the vacation mode immediately.", + "fields": { + "accesspoint_id": { + "name": "Accesspoint ID", + "description": "The ID of the Homematic IP Access Point." + } + } + }, + "set_active_climate_profile": { + "name": "Set active climate profile", + "description": "Sets the active climate profile index.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "The ID of the climate entity. Use 'all' keyword to switch the profile for all entities." + }, + "climate_profile_index": { + "name": "Climate profile index", + "description": "The index of the climate profile." + } + } + }, + "dump_hap_config": { + "name": "Dump hap config", + "description": "Dumps the configuration of the Homematic IP Access Point(s).", + "fields": { + "config_output_path": { + "name": "Config output path", + "description": "(Default is 'Your home-assistant config directory') Path where to store the config." + }, + "config_output_file_prefix": { + "name": "Config output file prefix", + "description": "Name of the config file. The SGTIN of the AP will always be appended." + }, + "anonymize": { + "name": "Anonymize", + "description": "Should the Configuration be anonymized?" + } + } + }, + "reset_energy_counter": { + "name": "Reset energy counter", + "description": "Resets the energy counter of a measuring entity.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "The ID of the measuring entity. Use 'all' keyword to reset all energy counters." + } + } + } } } diff --git a/homeassistant/components/html5/services.yaml b/homeassistant/components/html5/services.yaml index f6b76e67cd7952..929eb5a2dc1251 100644 --- a/homeassistant/components/html5/services.yaml +++ b/homeassistant/components/html5/services.yaml @@ -1,16 +1,10 @@ dismiss: - name: Dismiss - description: Dismiss a html5 notification. fields: target: - name: Target - description: An array of targets. example: ["my_phone", "my_tablet"] selector: object: data: - name: Data - description: Extended information of notification. Supports tag. example: '{ "tag": "tagname" }' selector: object: diff --git a/homeassistant/components/html5/strings.json b/homeassistant/components/html5/strings.json new file mode 100644 index 00000000000000..fa69025c43c1b8 --- /dev/null +++ b/homeassistant/components/html5/strings.json @@ -0,0 +1,18 @@ +{ + "services": { + "dismiss": { + "name": "Dismiss", + "description": "Dismisses a html5 notification.", + "fields": { + "target": { + "name": "Target", + "description": "An array of targets." + }, + "data": { + "name": "Data", + "description": "Extended information of notification. Supports tag." + } + } + } + } +} diff --git a/homeassistant/components/huawei_lte/services.yaml b/homeassistant/components/huawei_lte/services.yaml index 711064b435e24c..9d0cf5d91e658d 100644 --- a/homeassistant/components/huawei_lte/services.yaml +++ b/homeassistant/components/huawei_lte/services.yaml @@ -1,46 +1,27 @@ clear_traffic_statistics: - name: Clear traffic statistics - description: Clear traffic statistics. fields: url: - name: URL - description: URL of router to clear; optional when only one is configured. example: http://192.168.100.1/ selector: text: reboot: - name: Reboot - description: Reboot router. fields: url: - name: URL - description: URL of router to reboot; optional when only one is configured. example: http://192.168.100.1/ selector: text: resume_integration: - name: Resume integration - description: Resume suspended integration. fields: url: - name: URL - description: URL of router to resume integration for; optional when only one is configured. example: http://192.168.100.1/ selector: text: suspend_integration: - name: Suspend integration - description: > - Suspend integration. Suspending logs the integration out from the router, and stops accessing it. - Useful e.g. if accessing the router web interface from another source such as a web browser is temporarily required. - Invoke the resume_integration service to resume. fields: url: - name: URL - description: URL of router to resume integration for; optional when only one is configured. example: http://192.168.100.1/ selector: text: diff --git a/homeassistant/components/huawei_lte/strings.json b/homeassistant/components/huawei_lte/strings.json index 0eb68c959ac6fc..6f85187cfeb480 100644 --- a/homeassistant/components/huawei_lte/strings.json +++ b/homeassistant/components/huawei_lte/strings.json @@ -48,5 +48,47 @@ } } } + }, + "services": { + "clear_traffic_statistics": { + "name": "Clear traffic statistics", + "description": "Clears traffic statistics.", + "fields": { + "url": { + "name": "URL", + "description": "URL of router to clear; optional when only one is configured." + } + } + }, + "reboot": { + "name": "Reboot", + "description": "Reboots router.", + "fields": { + "url": { + "name": "URL", + "description": "URL of router to reboot; optional when only one is configured." + } + } + }, + "resume_integration": { + "name": "Resume integration", + "description": "Resumes suspended integration.", + "fields": { + "url": { + "name": "URL", + "description": "URL of router to resume integration for; optional when only one is configured." + } + } + }, + "suspend_integration": { + "name": "Suspend integration", + "description": "Suspends integration. Suspending logs the integration out from the router, and stops accessing it. Useful e.g. if accessing the router web interface from another source such as a web browser is temporarily required. Invoke the resume_integration service to resume.\n.", + "fields": { + "url": { + "name": "URL", + "description": "URL of router to resume integration for; optional when only one is configured." + } + } + } } } diff --git a/homeassistant/components/hue/services.yaml b/homeassistant/components/hue/services.yaml index b06c3934152257..a9ea57d7828e12 100644 --- a/homeassistant/components/hue/services.yaml +++ b/homeassistant/components/hue/services.yaml @@ -2,61 +2,42 @@ # legacy hue_activate_scene to activate a scene hue_activate_scene: - name: Activate scene - description: Activate a hue scene stored in the hue hub. fields: group_name: - name: Group - description: Name of hue group/room from the hue app. example: "Living Room" selector: text: scene_name: - name: Scene - description: Name of hue scene from the hue app. example: "Energize" selector: text: dynamic: - name: Dynamic - description: Enable dynamic mode of the scene (V2 bridges and supported scenes only). selector: boolean: # entity service to activate a Hue scene (V2) activate_scene: - name: Activate Hue Scene - description: Activate a Hue scene with more control over the options. target: entity: domain: scene integration: hue fields: transition: - name: Transition - description: Transition duration it takes to bring devices to the state - defined in the scene. selector: number: min: 0 max: 3600 unit_of_measurement: seconds dynamic: - name: Dynamic - description: Enable dynamic mode of the scene. selector: boolean: speed: - name: Speed - description: Speed of dynamic palette for this scene advanced: true selector: number: min: 0 max: 100 brightness: - name: Brightness - description: Set brightness for the scene. advanced: true selector: number: diff --git a/homeassistant/components/hue/strings.json b/homeassistant/components/hue/strings.json index a44eea0fe335d7..54895b6e3b2435 100644 --- a/homeassistant/components/hue/strings.json +++ b/homeassistant/components/hue/strings.json @@ -59,7 +59,6 @@ "remote_button_short_release": "\"{subtype}\" released", "remote_double_button_long_press": "Both \"{subtype}\" released after long press", "remote_double_button_short_press": "Both \"{subtype}\" released", - "initial_press": "\"{subtype}\" pressed initially", "repeat": "\"{subtype}\" held down", "short_release": "\"{subtype}\" released after short press", @@ -79,5 +78,47 @@ } } } + }, + "services": { + "hue_activate_scene": { + "name": "Activate scene", + "description": "Activates a hue scene stored in the hue hub.", + "fields": { + "group_name": { + "name": "Group", + "description": "Name of hue group/room from the hue app." + }, + "scene_name": { + "name": "Scene", + "description": "Name of hue scene from the hue app." + }, + "dynamic": { + "name": "Dynamic", + "description": "Enable dynamic mode of the scene (V2 bridges and supported scenes only)." + } + } + }, + "activate_scene": { + "name": "Activate Hue scene", + "description": "Activates a Hue scene with more control over the options.", + "fields": { + "transition": { + "name": "Transition", + "description": "Transition duration it takes to bring devices to the state defined in the scene." + }, + "dynamic": { + "name": "Dynamic", + "description": "Enable dynamic mode of the scene." + }, + "speed": { + "name": "Speed", + "description": "Speed of dynamic palette for this scene." + }, + "brightness": { + "name": "Brightness", + "description": "Set brightness for the scene." + } + } + } } } From eb3b56798d1a831a2db828c2acb5a515b118f4c7 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 12:32:25 +0200 Subject: [PATCH 074/154] Migrate conversation services to support translations (#96365) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- .../components/conversation/services.yaml | 8 ------- .../components/conversation/strings.json | 24 ++++++++++++++++++- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/conversation/services.yaml b/homeassistant/components/conversation/services.yaml index 1a28044dcb5d9f..7b6717eec6d3e9 100644 --- a/homeassistant/components/conversation/services.yaml +++ b/homeassistant/components/conversation/services.yaml @@ -1,24 +1,16 @@ # Describes the format for available component services process: - name: Process - description: Launch a conversation from a transcribed text. fields: text: - name: Text - description: Transcribed text example: Turn all lights on required: true selector: text: language: - name: Language - description: Language of text. Defaults to server language example: NL selector: text: agent_id: - name: Agent - description: Assist engine to process your request example: homeassistant selector: conversation_agent: diff --git a/homeassistant/components/conversation/strings.json b/homeassistant/components/conversation/strings.json index dc6f2b5f52bdd0..15e783c0d90afb 100644 --- a/homeassistant/components/conversation/strings.json +++ b/homeassistant/components/conversation/strings.json @@ -1 +1,23 @@ -{ "title": "Conversation" } +{ + "title": "Conversation", + "services": { + "process": { + "name": "Process", + "description": "Launches a conversation from a transcribed text.", + "fields": { + "text": { + "name": "Text", + "description": "Transcribed text input." + }, + "language": { + "name": "Language", + "description": "Language of text. Defaults to server language." + }, + "agent_id": { + "name": "Agent", + "description": "Conversation agent to process your request. The conversation agent is the brains of your assistant. It processes the incoming text commands." + } + } + } + } +} From d0258c8fc8cf43050ae2c37e4ab4bd3f95615356 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 12:53:24 +0200 Subject: [PATCH 075/154] Migrate switch services to support translations (#96405) --- homeassistant/components/switch/services.yaml | 6 ------ homeassistant/components/switch/strings.json | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/switch/services.yaml b/homeassistant/components/switch/services.yaml index 33f66070bfbfda..5da203d8a80007 100644 --- a/homeassistant/components/switch/services.yaml +++ b/homeassistant/components/switch/services.yaml @@ -1,22 +1,16 @@ # Describes the format for available switch services turn_on: - name: Turn on - description: Turn a switch on target: entity: domain: switch turn_off: - name: Turn off - description: Turn a switch off target: entity: domain: switch toggle: - name: Toggle - description: Toggles a switch state target: entity: domain: switch diff --git a/homeassistant/components/switch/strings.json b/homeassistant/components/switch/strings.json index 70cd45f4d2194f..ae5a3165cd966e 100644 --- a/homeassistant/components/switch/strings.json +++ b/homeassistant/components/switch/strings.json @@ -30,5 +30,19 @@ "outlet": { "name": "Outlet" } + }, + "services": { + "turn_on": { + "name": "Turn on", + "description": "Turns a switch on." + }, + "turn_off": { + "name": "Turn off", + "description": "Turns a switch off." + }, + "toggle": { + "name": "Toggle", + "description": "Toggles a switch on/off." + } } } From c6a9c6c94872f0d259c1acb8ba8a64c98c7e7587 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 13:42:29 +0200 Subject: [PATCH 076/154] Migrate date services to support translations (#96317) --- homeassistant/components/date/services.yaml | 4 ---- homeassistant/components/date/strings.json | 12 ++++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/date/services.yaml b/homeassistant/components/date/services.yaml index 7ce1210f809256..aebf5630205b1b 100644 --- a/homeassistant/components/date/services.yaml +++ b/homeassistant/components/date/services.yaml @@ -1,13 +1,9 @@ set_value: - name: Set Date - description: Set the date for a date entity. target: entity: domain: date fields: date: - name: Date - description: The date to set. required: true example: "2022/11/01" selector: diff --git a/homeassistant/components/date/strings.json b/homeassistant/components/date/strings.json index 110a4cabb921fb..9e88d3b567641f 100644 --- a/homeassistant/components/date/strings.json +++ b/homeassistant/components/date/strings.json @@ -4,5 +4,17 @@ "_": { "name": "[%key:component::date::title%]" } + }, + "services": { + "set_value": { + "name": "Set date", + "description": "Sets the date.", + "fields": { + "date": { + "name": "Date", + "description": "The date to set." + } + } + } } } From 0ca8a2618475d9bab6b6fc8e0655be6e4b2421fc Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 13:42:53 +0200 Subject: [PATCH 077/154] Migrate datetime services to support translations (#96318) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/datetime/services.yaml | 4 ---- homeassistant/components/datetime/strings.json | 12 ++++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/datetime/services.yaml b/homeassistant/components/datetime/services.yaml index b5cce19e88b70e..fb6f798e9bd89b 100644 --- a/homeassistant/components/datetime/services.yaml +++ b/homeassistant/components/datetime/services.yaml @@ -1,13 +1,9 @@ set_value: - name: Set Date/Time - description: Set the date/time for a datetime entity. target: entity: domain: datetime fields: datetime: - name: Date & Time - description: The date/time to set. The time zone of the Home Assistant instance is assumed. required: true example: "2022/11/01 22:15" selector: diff --git a/homeassistant/components/datetime/strings.json b/homeassistant/components/datetime/strings.json index 3b97559018c770..503d7a2ca9e564 100644 --- a/homeassistant/components/datetime/strings.json +++ b/homeassistant/components/datetime/strings.json @@ -4,5 +4,17 @@ "_": { "name": "[%key:component::datetime::title%]" } + }, + "services": { + "set_value": { + "name": "Set date/time", + "description": "Sets the date/time for a datetime entity.", + "fields": { + "datetime": { + "name": "Date & Time", + "description": "The date/time to set. The time zone of the Home Assistant instance is assumed." + } + } + } } } From cbddade4bf38b57d5e0b72717ebadcfb982173a3 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 13:44:15 +0200 Subject: [PATCH 078/154] Migrate logbook services to support translations (#96341) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- .../components/logbook/services.yaml | 10 ------- homeassistant/components/logbook/strings.json | 26 +++++++++++++++++++ 2 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 homeassistant/components/logbook/strings.json diff --git a/homeassistant/components/logbook/services.yaml b/homeassistant/components/logbook/services.yaml index 3f6886280325df..c6722dad10bdda 100644 --- a/homeassistant/components/logbook/services.yaml +++ b/homeassistant/components/logbook/services.yaml @@ -1,29 +1,19 @@ log: - name: Log - description: Create a custom entry in your logbook. fields: name: - name: Name - description: Custom name for an entity, can be referenced with entity_id. required: true example: "Kitchen" selector: text: message: - name: Message - description: Message of the custom logbook entry. required: true example: "is being used" selector: text: entity_id: - name: Entity ID - description: Entity to reference in custom logbook entry. selector: entity: domain: - name: Domain - description: Icon of domain to display in custom logbook entry. example: "light" selector: text: diff --git a/homeassistant/components/logbook/strings.json b/homeassistant/components/logbook/strings.json new file mode 100644 index 00000000000000..10ebcc68f64b3e --- /dev/null +++ b/homeassistant/components/logbook/strings.json @@ -0,0 +1,26 @@ +{ + "services": { + "log": { + "name": "Log", + "description": "Creates a custom entry in the logbook.", + "fields": { + "name": { + "name": "Name", + "description": "Custom name for an entity, can be referenced using an `entity_id`." + }, + "message": { + "name": "Message", + "description": "Message of the logbook entry." + }, + "entity_id": { + "name": "Entity ID", + "description": "Entity to reference in the logbook entry." + }, + "domain": { + "name": "Domain", + "description": "Determines which icon is used in the logbook entry. The icon illustrates the integration domain related to this logbook entry." + } + } + } + } +} From 6a1cd628aa4c45394550e6c70b9f768fe8d1a82a Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 13:45:38 +0200 Subject: [PATCH 079/154] Migrate script services to support translations (#96401) --- homeassistant/components/script/services.yaml | 9 --------- homeassistant/components/script/strings.json | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/script/services.yaml b/homeassistant/components/script/services.yaml index 1d3c0e8a8a9bbb..6fc3d81f19625e 100644 --- a/homeassistant/components/script/services.yaml +++ b/homeassistant/components/script/services.yaml @@ -1,26 +1,17 @@ # Describes the format for available python_script services reload: - name: Reload - description: Reload all the available scripts - turn_on: - name: Turn on - description: Turn on script target: entity: domain: script turn_off: - name: Turn off - description: Turn off script target: entity: domain: script toggle: - name: Toggle - description: Toggle script target: entity: domain: script diff --git a/homeassistant/components/script/strings.json b/homeassistant/components/script/strings.json index b9624f16a31348..e4f1b3fcd4f4bb 100644 --- a/homeassistant/components/script/strings.json +++ b/homeassistant/components/script/strings.json @@ -31,5 +31,23 @@ } } } + }, + "services": { + "reload": { + "name": "Reload", + "description": "Reloads all the available scripts." + }, + "turn_on": { + "name": "Turn on", + "description": "Runs the sequence of actions defined in a script." + }, + "turn_off": { + "name": "Turn off", + "description": "Stops a running script." + }, + "toggle": { + "name": "Toggle", + "description": "Toggle a script. Starts it, if isn't running, stops it otherwise." + } } } From ce5246a8cdc7ddba85e9bc07a556c3ad08726726 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 13:47:47 +0200 Subject: [PATCH 080/154] Migrate homeassistant services to support translations (#96388) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- .../components/homeassistant/services.yaml | 41 ------------ .../components/homeassistant/strings.json | 66 +++++++++++++++++++ 2 files changed, 66 insertions(+), 41 deletions(-) diff --git a/homeassistant/components/homeassistant/services.yaml b/homeassistant/components/homeassistant/services.yaml index 2fe27769c3fbc5..899fee357fd527 100644 --- a/homeassistant/components/homeassistant/services.yaml +++ b/homeassistant/components/homeassistant/services.yaml @@ -1,88 +1,47 @@ check_config: - name: Check configuration - description: - Check the Home Assistant configuration files for errors. Errors will be - displayed in the Home Assistant log. - reload_core_config: - name: Reload core configuration - description: Reload the core configuration. - restart: - name: Restart - description: Restart the Home Assistant service. - set_location: - name: Set location - description: Update the Home Assistant location. fields: latitude: - name: Latitude - description: Latitude of your location. required: true example: 32.87336 selector: text: longitude: - name: Longitude - description: Longitude of your location. required: true example: 117.22743 selector: text: stop: - name: Stop - description: Stop the Home Assistant service. - toggle: - name: Generic toggle - description: Generic service to toggle devices on/off under any domain target: entity: {} turn_on: - name: Generic turn on - description: Generic service to turn devices on under any domain. target: entity: {} turn_off: - name: Generic turn off - description: Generic service to turn devices off under any domain. target: entity: {} update_entity: - name: Update entity - description: Force one or more entities to update its data target: entity: {} reload_custom_templates: - name: Reload custom Jinja2 templates - description: >- - Reload Jinja2 templates found in the custom_templates folder in your config. - New values will be applied on the next render of the template. - reload_config_entry: - name: Reload config entry - description: Reload a config entry that matches a target. target: entity: {} device: {} fields: entry_id: advanced: true - name: Config entry id - description: A configuration entry id required: false example: 8955375327824e14ba89e4b29cc3ec9a selector: text: save_persistent_states: - name: Save Persistent States - description: - Save the persistent states (for entities derived from RestoreEntity) immediately. - Maintain the normal periodic saving interval. diff --git a/homeassistant/components/homeassistant/strings.json b/homeassistant/components/homeassistant/strings.json index 89da615cf31111..5a02cd196659b4 100644 --- a/homeassistant/components/homeassistant/strings.json +++ b/homeassistant/components/homeassistant/strings.json @@ -45,5 +45,71 @@ "version": "Version", "virtualenv": "Virtual Environment" } + }, + "services": { + "check_config": { + "name": "Check configuration", + "description": "Checks the Home Assistant YAML-configuration files for errors. Errors will be shown in the Home Assistant logs." + }, + "reload_core_config": { + "name": "Reload core configuration", + "description": "Reloads the core configuration from the YAML-configuration." + }, + "restart": { + "name": "Restart", + "description": "Restarts Home Assistant." + }, + "set_location": { + "name": "Set location", + "description": "Updates the Home Assistant location.", + "fields": { + "latitude": { + "name": "Latitude", + "description": "Latitude of your location." + }, + "longitude": { + "name": "Longitude", + "description": "Longitude of your location." + } + } + }, + "stop": { + "name": "Stop", + "description": "Stops Home Assistant." + }, + "toggle": { + "name": "Generic toggle", + "description": "Generic service to toggle devices on/off under any domain." + }, + "turn_on": { + "name": "Generic turn on", + "description": "Generic service to turn devices on under any domain." + }, + "turn_off": { + "name": "Generic turn off", + "description": "Generic service to turn devices off under any domain." + }, + "update_entity": { + "name": "Update entity", + "description": "Forces one or more entities to update its data." + }, + "reload_custom_templates": { + "name": "Reload custom Jinja2 templates", + "description": "Reloads Jinja2 templates found in the `custom_templates` folder in your config. New values will be applied on the next render of the template." + }, + "reload_config_entry": { + "name": "Reload config entry", + "description": "Reloads the specified config entry.", + "fields": { + "entry_id": { + "name": "Config entry ID", + "description": "The configuration entry ID of the entry to be reloaded." + } + } + }, + "save_persistent_states": { + "name": "Save persistent states", + "description": "Saves the persistent states immediately. Maintains the normal periodic saving interval." + } } } From 22b23b2c34fbe9a53606fa41579b3c53f57b663b Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 13:47:58 +0200 Subject: [PATCH 081/154] Migrate hassio services to support translations (#96386) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/hassio/services.yaml | 70 ------- homeassistant/components/hassio/strings.json | 196 +++++++++++++++++- 2 files changed, 186 insertions(+), 80 deletions(-) diff --git a/homeassistant/components/hassio/services.yaml b/homeassistant/components/hassio/services.yaml index 60b547354932f6..33eb1e88ed3764 100644 --- a/homeassistant/components/hassio/services.yaml +++ b/homeassistant/components/hassio/services.yaml @@ -1,193 +1,123 @@ addon_start: - name: Start add-on - description: Start add-on. fields: addon: - name: Add-on required: true - description: The add-on slug. example: core_ssh selector: addon: addon_restart: - name: Restart add-on. - description: Restart add-on. fields: addon: - name: Add-on required: true - description: The add-on slug. example: core_ssh selector: addon: addon_stdin: - name: Write data to add-on stdin. - description: Write data to add-on stdin. fields: addon: - name: Add-on required: true - description: The add-on slug. example: core_ssh selector: addon: addon_stop: - name: Stop add-on. - description: Stop add-on. fields: addon: - name: Add-on required: true - description: The add-on slug. example: core_ssh selector: addon: addon_update: - name: Update add-on. - description: Update add-on. This service should be used with caution since add-on updates can contain breaking changes. It is highly recommended that you review release notes/change logs before updating an add-on. fields: addon: - name: Add-on required: true - description: The add-on slug. example: core_ssh selector: addon: host_reboot: - name: Reboot the host system. - description: Reboot the host system. - host_shutdown: - name: Poweroff the host system. - description: Poweroff the host system. - backup_full: - name: Create a full backup. - description: Create a full backup. fields: name: - name: Name - description: Optional (default = current date and time). example: "Backup 1" selector: text: password: - name: Password - description: Optional password. example: "password" selector: text: compressed: - name: Compressed - description: Use compressed archives default: true selector: boolean: location: - name: Location - description: Name of a backup network storage to put backup (or /backup) example: my_backup_mount selector: backup_location: backup_partial: - name: Create a partial backup. - description: Create a partial backup. fields: homeassistant: - name: Home Assistant settings - description: Backup Home Assistant settings selector: boolean: addons: - name: Add-ons - description: Optional list of add-on slugs. example: ["core_ssh", "core_samba", "core_mosquitto"] selector: object: folders: - name: Folders - description: Optional list of directories. example: ["homeassistant", "share"] selector: object: name: - name: Name - description: Optional (default = current date and time). example: "Partial backup 1" selector: text: password: - name: Password - description: Optional password. example: "password" selector: text: compressed: - name: Compressed - description: Use compressed archives default: true selector: boolean: location: - name: Location - description: Name of a backup network storage to put backup (or /backup) example: my_backup_mount selector: backup_location: restore_full: - name: Restore from full backup. - description: Restore from full backup. fields: slug: - name: Slug required: true - description: Slug of backup to restore from. selector: text: password: - name: Password - description: Optional password. example: "password" selector: text: restore_partial: - name: Restore from partial backup. - description: Restore from partial backup. fields: slug: - name: Slug required: true - description: Slug of backup to restore from. selector: text: homeassistant: - name: Home Assistant settings - description: Restore Home Assistant selector: boolean: folders: - name: Folders - description: Optional list of directories. example: ["homeassistant", "share"] selector: object: addons: - name: Add-ons - description: Optional list of add-on slugs. example: ["core_ssh", "core_samba", "core_mosquitto"] selector: object: password: - name: Password - description: Optional password. example: "password" selector: text: diff --git a/homeassistant/components/hassio/strings.json b/homeassistant/components/hassio/strings.json index f9c212f946c912..fa8fc2d2da84d8 100644 --- a/homeassistant/components/hassio/strings.json +++ b/homeassistant/components/hassio/strings.json @@ -184,18 +184,194 @@ }, "entity": { "binary_sensor": { - "state": { "name": "Running" } + "state": { + "name": "Running" + } }, "sensor": { - "agent_version": { "name": "OS Agent version" }, - "apparmor_version": { "name": "Apparmor version" }, - "cpu_percent": { "name": "CPU percent" }, - "disk_free": { "name": "Disk free" }, - "disk_total": { "name": "Disk total" }, - "disk_used": { "name": "Disk used" }, - "memory_percent": { "name": "Memory percent" }, - "version": { "name": "Version" }, - "version_latest": { "name": "Newest version" } + "agent_version": { + "name": "OS Agent version" + }, + "apparmor_version": { + "name": "Apparmor version" + }, + "cpu_percent": { + "name": "CPU percent" + }, + "disk_free": { + "name": "Disk free" + }, + "disk_total": { + "name": "Disk total" + }, + "disk_used": { + "name": "Disk used" + }, + "memory_percent": { + "name": "Memory percent" + }, + "version": { + "name": "Version" + }, + "version_latest": { + "name": "Newest version" + } + } + }, + "services": { + "addon_start": { + "name": "Start add-on", + "description": "Starts an add-on.", + "fields": { + "addon": { + "name": "Add-on", + "description": "The add-on slug." + } + } + }, + "addon_restart": { + "name": "Restart add-on.", + "description": "Restarts an add-on.", + "fields": { + "addon": { + "name": "[%key:component::hassio::services::addon_start::fields::addon::name%]", + "description": "[%key:component::hassio::services::addon_start::fields::addon::description%]" + } + } + }, + "addon_stdin": { + "name": "Write data to add-on stdin.", + "description": "Writes data to add-on stdin.", + "fields": { + "addon": { + "name": "[%key:component::hassio::services::addon_start::fields::addon::name%]", + "description": "[%key:component::hassio::services::addon_start::fields::addon::description%]" + } + } + }, + "addon_stop": { + "name": "Stop add-on.", + "description": "Stops an add-on.", + "fields": { + "addon": { + "name": "[%key:component::hassio::services::addon_start::fields::addon::name%]", + "description": "[%key:component::hassio::services::addon_start::fields::addon::description%]" + } + } + }, + "addon_update": { + "name": "Update add-on.", + "description": "Updates an add-on. This service should be used with caution since add-on updates can contain breaking changes. It is highly recommended that you review release notes/change logs before updating an add-on.", + "fields": { + "addon": { + "name": "[%key:component::hassio::services::addon_start::fields::addon::name%]", + "description": "[%key:component::hassio::services::addon_start::fields::addon::description%]" + } + } + }, + "host_reboot": { + "name": "Reboot the host system.", + "description": "Reboots the host system." + }, + "host_shutdown": { + "name": "Power off the host system.", + "description": "Powers off the host system." + }, + "backup_full": { + "name": "Create a full backup.", + "description": "Creates a full backup.", + "fields": { + "name": { + "name": "Name", + "description": "Optional (default = current date and time)." + }, + "password": { + "name": "Password", + "description": "Password to protect the backup with." + }, + "compressed": { + "name": "Compressed", + "description": "Compresses the backup files." + }, + "location": { + "name": "Location", + "description": "Name of a backup network storage to host backups." + } + } + }, + "backup_partial": { + "name": "Create a partial backup.", + "description": "Creates a partial backup.", + "fields": { + "homeassistant": { + "name": "Home Assistant settings", + "description": "Includes Home Assistant settings in the backup." + }, + "addons": { + "name": "Add-ons", + "description": "List of add-ons to include in the backup. Use the name slug of the add-on." + }, + "folders": { + "name": "Folders", + "description": "List of directories to include in the backup." + }, + "name": { + "name": "[%key:component::hassio::services::backup_full::fields::name::name%]", + "description": "[%key:component::hassio::services::backup_full::fields::name::description%]" + }, + "password": { + "name": "[%key:component::hassio::services::backup_full::fields::password::name%]", + "description": "[%key:component::hassio::services::backup_full::fields::password::description%]" + }, + "compressed": { + "name": "[%key:component::hassio::services::backup_full::fields::compressed::name%]", + "description": "[%key:component::hassio::services::backup_full::fields::compressed::description%]" + }, + "location": { + "name": "[%key:component::hassio::services::backup_full::fields::location::name%]", + "description": "[%key:component::hassio::services::backup_full::fields::location::description%]" + } + } + }, + "restore_full": { + "name": "Restore from full backup.", + "description": "Restores from full backup.", + "fields": { + "slug": { + "name": "Slug", + "description": "Slug of backup to restore from." + }, + "password": { + "name": "[%key:component::hassio::services::backup_full::fields::password::name%]", + "description": "Optional password." + } + } + }, + "restore_partial": { + "name": "Restore from partial backup.", + "description": "Restores from a partial backup.", + "fields": { + "slug": { + "name": "[%key:component::hassio::services::restore_full::fields::slug::name%]", + "description": "[%key:component::hassio::services::restore_full::fields::slug::description%]" + }, + "homeassistant": { + "name": "[%key:component::hassio::services::backup_partial::fields::homeassistant::name%]", + "description": "Restores Home Assistant." + }, + "folders": { + "name": "[%key:component::hassio::services::backup_partial::fields::folders::name%]", + "description": "[%key:component::hassio::services::backup_partial::fields::folders::description%]" + }, + "addons": { + "name": "[%key:component::hassio::services::backup_partial::fields::addons::name%]", + "description": "[%key:component::hassio::services::backup_partial::fields::addons::description%]" + }, + "password": { + "name": "[%key:component::hassio::services::backup_full::fields::password::name%]", + "description": "[%key:component::hassio::services::restore_full::fields::password::description%]" + } + } } } } From 9ef62c75990835bdaca52128e8b3acc417a1aa7d Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 13:49:32 +0200 Subject: [PATCH 082/154] Migrate scene services to support translations (#96390) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/scene/services.yaml | 23 --------- homeassistant/components/scene/strings.json | 52 +++++++++++++++++++- 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/homeassistant/components/scene/services.yaml b/homeassistant/components/scene/services.yaml index 202b4a98aa9464..acd98b102553a7 100644 --- a/homeassistant/components/scene/services.yaml +++ b/homeassistant/components/scene/services.yaml @@ -1,16 +1,11 @@ # Describes the format for available scene services turn_on: - name: Activate - description: Activate a scene. target: entity: domain: scene fields: transition: - name: Transition - description: Transition duration it takes to bring devices to the state - defined in the scene. selector: number: min: 0 @@ -18,16 +13,9 @@ turn_on: unit_of_measurement: seconds reload: - name: Reload - description: Reload the scene configuration. - apply: - name: Apply - description: Activate a scene with configuration. fields: entities: - name: Entities state - description: The entities and the state that they need to be. required: true example: | light.kitchen: "on" @@ -37,9 +25,6 @@ apply: selector: object: transition: - name: Transition - description: Transition duration it takes to bring devices to the state - defined in the scene. selector: number: min: 0 @@ -47,19 +32,13 @@ apply: unit_of_measurement: seconds create: - name: Create - description: Creates a new scene. fields: scene_id: - name: Scene entity ID - description: The entity_id of the new scene. required: true example: all_lights selector: text: entities: - name: Entities state - description: The entities to control with the scene. example: | light.tv_back_light: "on" light.ceiling: @@ -68,8 +47,6 @@ create: selector: object: snapshot_entities: - name: Snapshot entities - description: The entities of which a snapshot is to be taken example: | - light.ceiling - light.kitchen diff --git a/homeassistant/components/scene/strings.json b/homeassistant/components/scene/strings.json index c92838ea322f71..f4011860c785ca 100644 --- a/homeassistant/components/scene/strings.json +++ b/homeassistant/components/scene/strings.json @@ -1 +1,51 @@ -{ "title": "Scene" } +{ + "title": "Scene", + "services": { + "turn_on": { + "name": "Activate", + "description": "Activates a scene.", + "fields": { + "transition": { + "name": "Transition", + "description": "Time it takes the devices to transition into the states defined in the scene." + } + } + }, + "reload": { + "name": "Reload", + "description": "Reloads the scenes from the YAML-configuration." + }, + "apply": { + "name": "Apply", + "description": "Activates a scene with configuration.", + "fields": { + "entities": { + "name": "Entities state", + "description": "List of entities and their target state." + }, + "transition": { + "name": "Transition", + "description": "Time it takes the devices to transition into the states defined in the scene." + } + } + }, + "create": { + "name": "Create", + "description": "Creates a new scene.", + "fields": { + "scene_id": { + "name": "Scene entity ID", + "description": "The entity ID of the new scene." + }, + "entities": { + "name": "Entities state", + "description": "List of entities and their target state. If your entities are already in the target state right now, use `snapshot_entities` instead." + }, + "snapshot_entities": { + "name": "Snapshot entities", + "description": "List of entities to be included in the snapshot. By taking a snapshot, you record the current state of those entities. If you do not want to use the current state of all your entities for this scene, you can combine the `snapshot_entities` with `entities`." + } + } + } + } +} From aca91db8b574f912351a3d2dc8a9a34c58698231 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 13:49:51 +0200 Subject: [PATCH 083/154] Migrate water_heater services to support translations (#96389) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- .../components/water_heater/services.yaml | 14 -------- .../components/water_heater/strings.json | 36 +++++++++++++++++++ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/homeassistant/components/water_heater/services.yaml b/homeassistant/components/water_heater/services.yaml index a3b372f219e6f4..b42109ee649960 100644 --- a/homeassistant/components/water_heater/services.yaml +++ b/homeassistant/components/water_heater/services.yaml @@ -1,29 +1,21 @@ # Describes the format for available water_heater services set_away_mode: - name: Set away mode - description: Turn away mode on/off for water_heater device. target: entity: domain: water_heater fields: away_mode: - name: Away mode - description: New value of away mode. required: true selector: boolean: set_temperature: - name: Set temperature - description: Set target temperature of water_heater device. target: entity: domain: water_heater fields: temperature: - name: Temperature - description: New target temperature for water heater. required: true selector: number: @@ -32,22 +24,16 @@ set_temperature: step: 0.5 unit_of_measurement: "°" operation_mode: - name: Operation mode - description: New value of operation mode. example: eco selector: text: set_operation_mode: - name: Set operation mode - description: Set operation mode for water_heater device. target: entity: domain: water_heater fields: operation_mode: - name: Operation mode - description: New value of operation mode. required: true example: eco selector: diff --git a/homeassistant/components/water_heater/strings.json b/homeassistant/components/water_heater/strings.json index b0a625d0016a15..a03e93cde41e54 100644 --- a/homeassistant/components/water_heater/strings.json +++ b/homeassistant/components/water_heater/strings.json @@ -18,5 +18,41 @@ "performance": "Performance" } } + }, + "services": { + "set_away_mode": { + "name": "Set away mode", + "description": "Turns away mode on/off.", + "fields": { + "away_mode": { + "name": "Away mode", + "description": "New value of away mode." + } + } + }, + "set_temperature": { + "name": "Set temperature", + "description": "Sets the target temperature.", + "fields": { + "temperature": { + "name": "Temperature", + "description": "New target temperature for the water heater." + }, + "operation_mode": { + "name": "Operation mode", + "description": "New value of the operation mode. For a list of possible modes, refer to the integration documentation." + } + } + }, + "set_operation_mode": { + "name": "Set operation mode", + "description": "Sets the operation mode.", + "fields": { + "operation_mode": { + "name": "[%key:component::water_heater::services::set_temperature::fields::operation_mode::name%]", + "description": "[%key:component::water_heater::services::set_temperature::fields::operation_mode::description%]" + } + } + } } } From 352ca0b7f8d996bfbca9937eaa162ba95ee6dbcb Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 13:54:06 +0200 Subject: [PATCH 084/154] Migrate fan services to support translations (#96325) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/fan/services.yaml | 40 +--------- homeassistant/components/fan/strings.json | 92 ++++++++++++++++++++++ 2 files changed, 95 insertions(+), 37 deletions(-) diff --git a/homeassistant/components/fan/services.yaml b/homeassistant/components/fan/services.yaml index db3bea9cad3a8d..8bd329ac8fec24 100644 --- a/homeassistant/components/fan/services.yaml +++ b/homeassistant/components/fan/services.yaml @@ -1,7 +1,5 @@ # Describes the format for available fan services set_preset_mode: - name: Set preset mode - description: Set preset mode for a fan device. target: entity: domain: fan @@ -9,16 +7,12 @@ set_preset_mode: - fan.FanEntityFeature.PRESET_MODE fields: preset_mode: - name: Preset mode - description: New value of preset mode. required: true example: "auto" selector: text: set_percentage: - name: Set speed percentage - description: Set fan speed percentage. target: entity: domain: fan @@ -26,8 +20,6 @@ set_percentage: - fan.FanEntityFeature.SET_SPEED fields: percentage: - name: Percentage - description: Percentage speed setting. required: true selector: number: @@ -36,15 +28,11 @@ set_percentage: unit_of_measurement: "%" turn_on: - name: Turn on - description: Turn fan on. target: entity: domain: fan fields: percentage: - name: Percentage - description: Percentage speed setting. filter: supported_features: - fan.FanEntityFeature.SET_SPEED @@ -54,8 +42,6 @@ turn_on: max: 100 unit_of_measurement: "%" preset_mode: - name: Preset mode - description: Preset mode setting. example: "auto" filter: supported_features: @@ -64,15 +50,11 @@ turn_on: text: turn_off: - name: Turn off - description: Turn fan off. target: entity: domain: fan oscillate: - name: Oscillate - description: Oscillate the fan. target: entity: domain: fan @@ -80,22 +62,16 @@ oscillate: - fan.FanEntityFeature.OSCILLATE fields: oscillating: - name: Oscillating - description: Flag to turn on/off oscillation. required: true selector: boolean: toggle: - name: Toggle - description: Toggle the fan on/off. target: entity: domain: fan set_direction: - name: Set direction - description: Set the fan rotation. target: entity: domain: fan @@ -103,20 +79,14 @@ set_direction: - fan.FanEntityFeature.DIRECTION fields: direction: - name: Direction - description: The direction to rotate. required: true selector: select: options: - - label: "Forward" - value: "forward" - - label: "Reverse" - value: "reverse" - + - "forward" + - "reverse" + translation_key: direction increase_speed: - name: Increase speed - description: Increase the speed of the fan by one speed or a percentage_step. target: entity: domain: fan @@ -126,7 +96,6 @@ increase_speed: percentage_step: advanced: true required: false - description: Increase speed by a percentage. selector: number: min: 0 @@ -134,8 +103,6 @@ increase_speed: unit_of_measurement: "%" decrease_speed: - name: Decrease speed - description: Decrease the speed of the fan by one speed or a percentage_step. target: entity: domain: fan @@ -145,7 +112,6 @@ decrease_speed: percentage_step: advanced: true required: false - description: Decrease speed by a percentage. selector: number: min: 0 diff --git a/homeassistant/components/fan/strings.json b/homeassistant/components/fan/strings.json index 0f3b88fd7f204d..d3a06edbee1b23 100644 --- a/homeassistant/components/fan/strings.json +++ b/homeassistant/components/fan/strings.json @@ -52,5 +52,97 @@ } } } + }, + "services": { + "set_preset_mode": { + "name": "Set preset mode", + "description": "Sets preset mode.", + "fields": { + "preset_mode": { + "name": "Preset mode", + "description": "Preset mode." + } + } + }, + "set_percentage": { + "name": "Set speed", + "description": "Sets the fan speed.", + "fields": { + "percentage": { + "name": "Percentage", + "description": "Speed of the fan." + } + } + }, + "turn_on": { + "name": "Turn on", + "description": "Turns fan on.", + "fields": { + "percentage": { + "name": "[%key:component::fan::services::set_percentage::fields::percentage::name%]", + "description": "[%key:component::fan::services::set_percentage::fields::percentage::description%]" + }, + "preset_mode": { + "name": "[%key:component::fan::services::set_preset_mode::fields::preset_mode::name%]", + "description": "[%key:component::fan::services::set_preset_mode::fields::preset_mode::description%]" + } + } + }, + "turn_off": { + "name": "Turn off", + "description": "Turns fan off." + }, + "oscillate": { + "name": "Oscillate", + "description": "Controls oscillatation of the fan.", + "fields": { + "oscillating": { + "name": "Oscillating", + "description": "Turn on/off oscillation." + } + } + }, + "toggle": { + "name": "Toggle", + "description": "Toggles the fan on/off." + }, + "set_direction": { + "name": "Set direction", + "description": "Sets the fan rotation direction.", + "fields": { + "direction": { + "name": "Direction", + "description": "Direction to rotate." + } + } + }, + "increase_speed": { + "name": "Increase speed", + "description": "Increases the speed of the fan.", + "fields": { + "percentage_step": { + "name": "Increment", + "description": "Increases the speed by a percentage step." + } + } + }, + "decrease_speed": { + "name": "Decrease speed", + "description": "Decreases the speed of the fan.", + "fields": { + "percentage_step": { + "name": "Decrement", + "description": "Decreases the speed by a percentage step." + } + } + } + }, + "selector": { + "direction": { + "options": { + "forward": "Forward", + "reverse": "Reverse" + } + } } } From c3871cc5aec171c76e2094a39d52545334b61e86 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 14:06:14 +0200 Subject: [PATCH 085/154] Migrate template services to support translations (#96414) --- homeassistant/components/template/services.yaml | 2 -- homeassistant/components/template/strings.json | 8 ++++++++ 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 homeassistant/components/template/strings.json diff --git a/homeassistant/components/template/services.yaml b/homeassistant/components/template/services.yaml index 6186bc6dccbef8..c983a105c93977 100644 --- a/homeassistant/components/template/services.yaml +++ b/homeassistant/components/template/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload all template entities. diff --git a/homeassistant/components/template/strings.json b/homeassistant/components/template/strings.json new file mode 100644 index 00000000000000..3222a0f1bdf5fc --- /dev/null +++ b/homeassistant/components/template/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "reload": { + "name": "Reload", + "description": "Reloads template entities from the YAML-configuration." + } + } +} From cccf436326e189a4bd9935ec7852e29f11a6424c Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 15:14:10 +0200 Subject: [PATCH 086/154] Migrate LaMetric services to support translations (#96415) --- .../components/lametric/services.yaml | 194 +++++------------- .../components/lametric/strings.json | 134 ++++++++++++ 2 files changed, 191 insertions(+), 137 deletions(-) diff --git a/homeassistant/components/lametric/services.yaml b/homeassistant/components/lametric/services.yaml index 3299245fbc0d8c..af04eac5f339ba 100644 --- a/homeassistant/components/lametric/services.yaml +++ b/homeassistant/components/lametric/services.yaml @@ -1,129 +1,70 @@ chart: - name: Display a chart - description: Display a chart on a LaMetric device. fields: device_id: &device_id - name: Device - description: The LaMetric device to display the chart on. required: true selector: device: integration: lametric data: - name: Data - description: The list of data points in the chart required: true example: "[1,2,3,4,5,4,3,2,1]" selector: object: sound: &sound - name: Sound - description: The notification sound to play. required: false selector: select: options: - - label: "Alarm 1" - value: "alarm1" - - label: "Alarm 2" - value: "alarm2" - - label: "Alarm 3" - value: "alarm3" - - label: "Alarm 4" - value: "alarm4" - - label: "Alarm 5" - value: "alarm5" - - label: "Alarm 6" - value: "alarm6" - - label: "Alarm 7" - value: "alarm7" - - label: "Alarm 8" - value: "alarm8" - - label: "Alarm 9" - value: "alarm9" - - label: "Alarm 10" - value: "alarm10" - - label: "Alarm 11" - value: "alarm11" - - label: "Alarm 12" - value: "alarm12" - - label: "Alarm 13" - value: "alarm13" - - label: "Bicycle" - value: "bicycle" - - label: "Car" - value: "car" - - label: "Cash" - value: "cash" - - label: "Cat" - value: "cat" - - label: "Dog 1" - value: "dog" - - label: "Dog 2" - value: "dog2" - - label: "Energy" - value: "energy" - - label: "Knock knock" - value: "knock-knock" - - label: "Letter email" - value: "letter_email" - - label: "Lose 1" - value: "lose1" - - label: "Lose 2" - value: "lose2" - - label: "Negative 1" - value: "negative1" - - label: "Negative 2" - value: "negative2" - - label: "Negative 3" - value: "negative3" - - label: "Negative 4" - value: "negative4" - - label: "Negative 5" - value: "negative5" - - label: "Notification 1" - value: "notification" - - label: "Notification 2" - value: "notification2" - - label: "Notification 3" - value: "notification3" - - label: "Notification 4" - value: "notification4" - - label: "Open door" - value: "open_door" - - label: "Positive 1" - value: "positive1" - - label: "Positive 2" - value: "positive2" - - label: "Positive 3" - value: "positive3" - - label: "Positive 4" - value: "positive4" - - label: "Positive 5" - value: "positive5" - - label: "Positive 6" - value: "positive6" - - label: "Statistic" - value: "statistic" - - label: "Thunder" - value: "thunder" - - label: "Water 1" - value: "water1" - - label: "Water 2" - value: "water2" - - label: "Win 1" - value: "win" - - label: "Win 2" - value: "win2" - - label: "Wind" - value: "wind" - - label: "Wind short" - value: "wind_short" + - "alarm1" + - "alarm2" + - "alarm3" + - "alarm4" + - "alarm5" + - "alarm6" + - "alarm7" + - "alarm8" + - "alarm9" + - "alarm10" + - "alarm11" + - "alarm12" + - "alarm13" + - "bicycle" + - "car" + - "cash" + - "cat" + - "dog" + - "dog2" + - "energy" + - "knock-knock" + - "letter_email" + - "lose1" + - "lose2" + - "negative1" + - "negative2" + - "negative3" + - "negative4" + - "negative5" + - "notification" + - "notification2" + - "notification3" + - "notification4" + - "open_door" + - "positive1" + - "positive2" + - "positive3" + - "positive4" + - "positive5" + - "positive6" + - "statistic" + - "thunder" + - "water1" + - "water2" + - "win" + - "win2" + - "wind" + - "wind_short" + translation_key: sound cycles: &cycles - name: Cycles - description: >- - The number of times to display the message. When set to 0, the message - will be displayed until dismissed. required: false default: 1 selector: @@ -132,56 +73,35 @@ chart: max: 10 mode: slider icon_type: &icon_type - name: Icon type - description: >- - The type of icon to display, indicating the nature of the notification. required: false default: "none" selector: select: mode: dropdown options: - - label: "None" - value: "none" - - label: "Info" - value: "info" - - label: "Alert" - value: "alert" + - "none" + - "info" + - "alert" + translation_key: icon_type priority: &priority - name: Priority - description: >- - The priority of the notification. When the device is running in - screensaver or kiosk mode, only critical priority notifications - will be accepted. required: false default: "info" selector: select: mode: dropdown options: - - label: "Info" - value: "info" - - label: "Warning" - value: "warning" - - label: "Critical" - value: "critical" - + - "info" + - "warning" + - "critical" + translation_key: priority message: - name: Display a message - description: Display a message with an optional icon on a LaMetric device. fields: device_id: *device_id message: - name: Message - description: The message to display. required: true selector: text: icon: - name: Icon - description: >- - The ID number of the icon or animation to display. List of all icons - and their IDs can be found at: https://developer.lametric.com/icons required: false selector: text: diff --git a/homeassistant/components/lametric/strings.json b/homeassistant/components/lametric/strings.json index 21cebe46f26e98..ac06e125b0c302 100644 --- a/homeassistant/components/lametric/strings.json +++ b/homeassistant/components/lametric/strings.json @@ -78,5 +78,139 @@ "name": "Bluetooth" } } + }, + "services": { + "chart": { + "name": "Display a chart", + "description": "Displays a chart on a LaMetric device.", + "fields": { + "device_id": { + "name": "Device", + "description": "The LaMetric device to display the chart on." + }, + "data": { + "name": "Data", + "description": "The list of data points in the chart." + }, + "sound": { + "name": "Sound", + "description": "The notification sound to play." + }, + "cycles": { + "name": "Cycles", + "description": "The number of times to display the message. When set to 0, the message will be displayed until dismissed." + }, + "icon_type": { + "name": "Icon type", + "description": "The type of icon to display, indicating the nature of the notification." + }, + "priority": { + "name": "Priority", + "description": "The priority of the notification. When the device is running in screensaver or kiosk mode, only critical priority notifications will be accepted." + } + } + }, + "message": { + "name": "Display a message", + "description": "Displays a message with an optional icon on a LaMetric device.", + "fields": { + "device_id": { + "name": "[%key:component::lametric::services::chart::fields::device_id::name%]", + "description": "The LaMetric device to display the message on." + }, + "message": { + "name": "Message", + "description": "The message to display." + }, + "icon": { + "name": "Icon", + "description": "The ID number of the icon or animation to display. List of all icons and their IDs can be found at: https://developer.lametric.com/icons." + }, + "sound": { + "name": "[%key:component::lametric::services::chart::fields::sound::name%]", + "description": "[%key:component::lametric::services::chart::fields::sound::description%]" + }, + "cycles": { + "name": "[%key:component::lametric::services::chart::fields::cycles::name%]", + "description": "[%key:component::lametric::services::chart::fields::cycles::description%]" + }, + "icon_type": { + "name": "[%key:component::lametric::services::chart::fields::icon_type::name%]", + "description": "[%key:component::lametric::services::chart::fields::icon_type::description%]" + }, + "priority": { + "name": "[%key:component::lametric::services::chart::fields::priority::name%]", + "description": "[%key:component::lametric::services::chart::fields::priority::description%]" + } + } + } + }, + "selector": { + "sound": { + "options": { + "alarm1": "Alarm 1", + "alarm2": "Alarm 2", + "alarm3": "Alarm 3", + "alarm4": "Alarm 4", + "alarm5": "Alarm 5", + "alarm6": "Alarm 6", + "alarm7": "Alarm 7", + "alarm8": "Alarm 8", + "alarm9": "Alarm 9", + "alarm10": "Alarm 10", + "alarm11": "Alarm 11", + "alarm12": "Alarm 12", + "alarm13": "Alarm 13", + "bicycle": "Bicycle", + "car": "Car", + "cash": "Cash", + "cat": "Cat", + "dog": "Dog 1", + "dog2": "Dog 2", + "energy": "Energy", + "knock-knock": "Knock knock", + "letter_email": "Letter email", + "lose1": "Lose 1", + "lose2": "Lose 2", + "negative1": "Negative 1", + "negative2": "Negative 2", + "negative3": "Negative 3", + "negative4": "Negative 4", + "negative5": "Negative 5", + "notification": "Notification 1", + "notification2": "Notification 2", + "notification3": "Notification 3", + "notification4": "Notification 4", + "open_door": "Open door", + "positive1": "Positive 1", + "positive2": "Positive 2", + "positive3": "Positive 3", + "positive4": "Positive 4", + "positive5": "Positive 5", + "positive6": "Positive 6", + "statistic": "Statistic", + "thunder": "Thunder", + "water1": "Water 1", + "water2": "Water 2", + "win": "Win 1", + "win2": "Win 2", + "wind": "Wind", + "wind_short": "Wind short" + } + }, + "icon_type": { + "options": { + "none": "None", + "info": "Info", + "alert": "Alert" + } + }, + "priority": { + "options": { + "info": "Info", + "warning": "Warning", + "critical": "Critical" + } + } } } From 878ed7cf219b1aa910a276a74b64dae8b72ca923 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 15:30:36 +0200 Subject: [PATCH 087/154] Migrate intent_script services to support translations (#96394) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/intent_script/services.yaml | 2 -- homeassistant/components/intent_script/strings.json | 8 ++++++++ 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 homeassistant/components/intent_script/strings.json diff --git a/homeassistant/components/intent_script/services.yaml b/homeassistant/components/intent_script/services.yaml index bb981dbc69cb4b..c983a105c93977 100644 --- a/homeassistant/components/intent_script/services.yaml +++ b/homeassistant/components/intent_script/services.yaml @@ -1,3 +1 @@ reload: - name: Reload - description: Reload the intent_script configuration. diff --git a/homeassistant/components/intent_script/strings.json b/homeassistant/components/intent_script/strings.json new file mode 100644 index 00000000000000..efd77d225f763b --- /dev/null +++ b/homeassistant/components/intent_script/strings.json @@ -0,0 +1,8 @@ +{ + "services": { + "reload": { + "name": "Reload", + "description": "Reloads the intent script from the YAML-configuration." + } + } +} From 6c4478392736b3a0f1485bcb5a1682d84288ebfc Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 15:36:57 +0200 Subject: [PATCH 088/154] Migrate Matter services to support translations (#96406) --- homeassistant/components/matter/services.yaml | 5 ----- homeassistant/components/matter/strings.json | 12 ++++++++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/matter/services.yaml b/homeassistant/components/matter/services.yaml index ff59a7efe63d34..c72187b2ffe915 100644 --- a/homeassistant/components/matter/services.yaml +++ b/homeassistant/components/matter/services.yaml @@ -1,11 +1,6 @@ open_commissioning_window: - name: Open Commissioning Window - description: > - Allow adding one of your devices to another Matter network by opening the commissioning window for this Matter device for 60 seconds. fields: device_id: - name: Device - description: The Matter device to add to the other Matter network. required: true selector: device: diff --git a/homeassistant/components/matter/strings.json b/homeassistant/components/matter/strings.json index dc5eb30df51a33..3d5ae9b6a61e13 100644 --- a/homeassistant/components/matter/strings.json +++ b/homeassistant/components/matter/strings.json @@ -50,5 +50,17 @@ "name": "Flow" } } + }, + "services": { + "open_commissioning_window": { + "name": "Open commissioning window", + "description": "Allows adding one of your devices to another Matter network by opening the commissioning window for this Matter device for 60 seconds.", + "fields": { + "device_id": { + "name": "Device", + "description": "The Matter device to add to the other Matter network." + } + } + } } } From f7ce9b1688a9bc9cb575b411c0d62e62826c016f Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Wed, 12 Jul 2023 16:08:15 +0200 Subject: [PATCH 089/154] Add support for gardena bluetooth (#95179) Add support for gardena bluetooth based water computers. --- .coveragerc | 4 + CODEOWNERS | 2 + .../components/gardena_bluetooth/__init__.py | 86 ++++++ .../gardena_bluetooth/config_flow.py | 138 ++++++++++ .../components/gardena_bluetooth/const.py | 3 + .../gardena_bluetooth/coordinator.py | 121 ++++++++ .../gardena_bluetooth/manifest.json | 17 ++ .../components/gardena_bluetooth/strings.json | 28 ++ .../components/gardena_bluetooth/switch.py | 74 +++++ homeassistant/generated/bluetooth.py | 6 + homeassistant/generated/config_flows.py | 1 + homeassistant/generated/integrations.json | 6 + requirements_all.txt | 3 + requirements_test_all.txt | 3 + .../components/gardena_bluetooth/__init__.py | 61 +++++ .../components/gardena_bluetooth/conftest.py | 30 ++ .../snapshots/test_config_flow.ambr | 258 ++++++++++++++++++ .../gardena_bluetooth/test_config_flow.py | 134 +++++++++ 18 files changed, 975 insertions(+) create mode 100644 homeassistant/components/gardena_bluetooth/__init__.py create mode 100644 homeassistant/components/gardena_bluetooth/config_flow.py create mode 100644 homeassistant/components/gardena_bluetooth/const.py create mode 100644 homeassistant/components/gardena_bluetooth/coordinator.py create mode 100644 homeassistant/components/gardena_bluetooth/manifest.json create mode 100644 homeassistant/components/gardena_bluetooth/strings.json create mode 100644 homeassistant/components/gardena_bluetooth/switch.py create mode 100644 tests/components/gardena_bluetooth/__init__.py create mode 100644 tests/components/gardena_bluetooth/conftest.py create mode 100644 tests/components/gardena_bluetooth/snapshots/test_config_flow.ambr create mode 100644 tests/components/gardena_bluetooth/test_config_flow.py diff --git a/.coveragerc b/.coveragerc index 912c472de3e19b..e10a23e9c31404 100644 --- a/.coveragerc +++ b/.coveragerc @@ -404,6 +404,10 @@ omit = homeassistant/components/garages_amsterdam/__init__.py homeassistant/components/garages_amsterdam/binary_sensor.py homeassistant/components/garages_amsterdam/sensor.py + homeassistant/components/gardena_bluetooth/__init__.py + homeassistant/components/gardena_bluetooth/const.py + homeassistant/components/gardena_bluetooth/coordinator.py + homeassistant/components/gardena_bluetooth/switch.py homeassistant/components/gc100/* homeassistant/components/geniushub/* homeassistant/components/geocaching/__init__.py diff --git a/CODEOWNERS b/CODEOWNERS index 16c0426d87f620..01f486e2704307 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -425,6 +425,8 @@ build.json @home-assistant/supervisor /tests/components/fully_kiosk/ @cgarwood /homeassistant/components/garages_amsterdam/ @klaasnicolaas /tests/components/garages_amsterdam/ @klaasnicolaas +/homeassistant/components/gardena_bluetooth/ @elupus +/tests/components/gardena_bluetooth/ @elupus /homeassistant/components/gdacs/ @exxamalte /tests/components/gdacs/ @exxamalte /homeassistant/components/generic/ @davet2001 diff --git a/homeassistant/components/gardena_bluetooth/__init__.py b/homeassistant/components/gardena_bluetooth/__init__.py new file mode 100644 index 00000000000000..05ac16381d1ddd --- /dev/null +++ b/homeassistant/components/gardena_bluetooth/__init__.py @@ -0,0 +1,86 @@ +"""The Gardena Bluetooth integration.""" +from __future__ import annotations + +import asyncio +import logging + +from bleak.backends.device import BLEDevice +from gardena_bluetooth.client import CachedConnection, Client +from gardena_bluetooth.const import DeviceConfiguration, DeviceInformation +from gardena_bluetooth.exceptions import CommunicationFailure + +from homeassistant.components import bluetooth +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import CONF_ADDRESS, Platform +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import ConfigEntryNotReady +from homeassistant.helpers.entity import DeviceInfo +import homeassistant.util.dt as dt_util + +from .const import DOMAIN +from .coordinator import Coordinator, DeviceUnavailable + +PLATFORMS: list[Platform] = [Platform.SWITCH] +LOGGER = logging.getLogger(__name__) +TIMEOUT = 20.0 +DISCONNECT_DELAY = 5 + + +def get_connection(hass: HomeAssistant, address: str) -> CachedConnection: + """Set up a cached client that keeps connection after last use.""" + + def _device_lookup() -> BLEDevice: + device = bluetooth.async_ble_device_from_address( + hass, address, connectable=True + ) + if not device: + raise DeviceUnavailable("Unable to find device") + return device + + return CachedConnection(DISCONNECT_DELAY, _device_lookup) + + +async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: + """Set up Gardena Bluetooth from a config entry.""" + + address = entry.data[CONF_ADDRESS] + client = Client(get_connection(hass, address)) + try: + sw_version = await client.read_char(DeviceInformation.firmware_version, None) + manufacturer = await client.read_char(DeviceInformation.manufacturer_name, None) + model = await client.read_char(DeviceInformation.model_number, None) + name = await client.read_char( + DeviceConfiguration.custom_device_name, entry.title + ) + uuids = await client.get_all_characteristics_uuid() + await client.update_timestamp(dt_util.now()) + except (asyncio.TimeoutError, CommunicationFailure, DeviceUnavailable) as exception: + await client.disconnect() + raise ConfigEntryNotReady( + f"Unable to connect to device {address} due to {exception}" + ) from exception + + device = DeviceInfo( + identifiers={(DOMAIN, address)}, + name=name, + sw_version=sw_version, + manufacturer=manufacturer, + model=model, + ) + + coordinator = Coordinator(hass, LOGGER, client, uuids, device, address) + + hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator + await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) + await coordinator.async_refresh() + + return True + + +async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: + """Unload a config entry.""" + if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): + coordinator: Coordinator = hass.data[DOMAIN].pop(entry.entry_id) + await coordinator.async_shutdown() + + return unload_ok diff --git a/homeassistant/components/gardena_bluetooth/config_flow.py b/homeassistant/components/gardena_bluetooth/config_flow.py new file mode 100644 index 00000000000000..3e9816750573a0 --- /dev/null +++ b/homeassistant/components/gardena_bluetooth/config_flow.py @@ -0,0 +1,138 @@ +"""Config flow for Gardena Bluetooth integration.""" +from __future__ import annotations + +import logging +from typing import Any + +from gardena_bluetooth.client import Client +from gardena_bluetooth.const import DeviceInformation, ScanService +from gardena_bluetooth.exceptions import CharacteristicNotFound, CommunicationFailure +from gardena_bluetooth.parse import ManufacturerData, ProductGroup +import voluptuous as vol + +from homeassistant import config_entries +from homeassistant.components.bluetooth import ( + BluetoothServiceInfo, + async_discovered_service_info, +) +from homeassistant.const import CONF_ADDRESS +from homeassistant.data_entry_flow import AbortFlow, FlowResult + +from . import get_connection +from .const import DOMAIN + +_LOGGER = logging.getLogger(__name__) + + +def _is_supported(discovery_info: BluetoothServiceInfo): + """Check if device is supported.""" + if ScanService not in discovery_info.service_uuids: + return False + + if not (data := discovery_info.manufacturer_data.get(ManufacturerData.company)): + _LOGGER.debug("Missing manufacturer data: %s", discovery_info) + return False + + manufacturer_data = ManufacturerData.decode(data) + if manufacturer_data.group != ProductGroup.WATER_CONTROL: + _LOGGER.debug("Unsupported device: %s", manufacturer_data) + return False + + return True + + +def _get_name(discovery_info: BluetoothServiceInfo): + if discovery_info.name and discovery_info.name != discovery_info.address: + return discovery_info.name + return "Gardena Device" + + +class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): + """Handle a config flow for Gardena Bluetooth.""" + + VERSION = 1 + + def __init__(self) -> None: + """Initialize the config flow.""" + self.devices: dict[str, str] = {} + self.address: str | None + + async def async_read_data(self): + """Try to connect to device and extract information.""" + client = Client(get_connection(self.hass, self.address)) + try: + model = await client.read_char(DeviceInformation.model_number) + _LOGGER.debug("Found device with model: %s", model) + except (CharacteristicNotFound, CommunicationFailure) as exception: + raise AbortFlow( + "cannot_connect", description_placeholders={"error": str(exception)} + ) from exception + finally: + await client.disconnect() + + return {CONF_ADDRESS: self.address} + + async def async_step_bluetooth( + self, discovery_info: BluetoothServiceInfo + ) -> FlowResult: + """Handle the bluetooth discovery step.""" + _LOGGER.debug("Discovered device: %s", discovery_info) + if not _is_supported(discovery_info): + return self.async_abort(reason="no_devices_found") + + self.address = discovery_info.address + self.devices = {discovery_info.address: _get_name(discovery_info)} + await self.async_set_unique_id(self.address) + self._abort_if_unique_id_configured() + return await self.async_step_confirm() + + async def async_step_confirm( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: + """Confirm discovery.""" + assert self.address + title = self.devices[self.address] + + if user_input is not None: + data = await self.async_read_data() + return self.async_create_entry(title=title, data=data) + + self.context["title_placeholders"] = { + "name": title, + } + + self._set_confirm_only() + return self.async_show_form( + step_id="confirm", + description_placeholders=self.context["title_placeholders"], + ) + + async def async_step_user( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: + """Handle the initial step.""" + if user_input is not None: + self.address = user_input[CONF_ADDRESS] + await self.async_set_unique_id(self.address, raise_on_progress=False) + self._abort_if_unique_id_configured() + return await self.async_step_confirm() + + current_addresses = self._async_current_ids() + for discovery_info in async_discovered_service_info(self.hass): + address = discovery_info.address + if address in current_addresses or not _is_supported(discovery_info): + continue + + self.devices[address] = _get_name(discovery_info) + + if not self.devices: + return self.async_abort(reason="no_devices_found") + + return self.async_show_form( + step_id="user", + data_schema=vol.Schema( + { + vol.Required(CONF_ADDRESS): vol.In(self.devices), + }, + ), + ) diff --git a/homeassistant/components/gardena_bluetooth/const.py b/homeassistant/components/gardena_bluetooth/const.py new file mode 100644 index 00000000000000..7de4c15b5fa98f --- /dev/null +++ b/homeassistant/components/gardena_bluetooth/const.py @@ -0,0 +1,3 @@ +"""Constants for the Gardena Bluetooth integration.""" + +DOMAIN = "gardena_bluetooth" diff --git a/homeassistant/components/gardena_bluetooth/coordinator.py b/homeassistant/components/gardena_bluetooth/coordinator.py new file mode 100644 index 00000000000000..fa7639dece0177 --- /dev/null +++ b/homeassistant/components/gardena_bluetooth/coordinator.py @@ -0,0 +1,121 @@ +"""Provides the DataUpdateCoordinator.""" +from __future__ import annotations + +from datetime import timedelta +import logging +from typing import Any + +from gardena_bluetooth.client import Client +from gardena_bluetooth.exceptions import ( + CharacteristicNoAccess, + GardenaBluetoothException, +) +from gardena_bluetooth.parse import Characteristic, CharacteristicType + +from homeassistant.components import bluetooth +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers.entity import DeviceInfo +from homeassistant.helpers.update_coordinator import ( + CoordinatorEntity, + DataUpdateCoordinator, + UpdateFailed, +) + +SCAN_INTERVAL = timedelta(seconds=60) +LOGGER = logging.getLogger(__name__) + + +class DeviceUnavailable(HomeAssistantError): + """Raised if device can't be found.""" + + +class Coordinator(DataUpdateCoordinator[dict[str, bytes]]): + """Class to manage fetching data.""" + + def __init__( + self, + hass: HomeAssistant, + logger: logging.Logger, + client: Client, + characteristics: set[str], + device_info: DeviceInfo, + address: str, + ) -> None: + """Initialize global data updater.""" + super().__init__( + hass=hass, + logger=logger, + name="Gardena Bluetooth Data Update Coordinator", + update_interval=SCAN_INTERVAL, + ) + self.address = address + self.data = {} + self.client = client + self.characteristics = characteristics + self.device_info = device_info + + async def async_shutdown(self) -> None: + """Shutdown coordinator and any connection.""" + await super().async_shutdown() + await self.client.disconnect() + + async def _async_update_data(self) -> dict[str, bytes]: + """Poll the device.""" + uuids: set[str] = { + uuid for context in self.async_contexts() for uuid in context + } + if not uuids: + return {} + + data: dict[str, bytes] = {} + for uuid in uuids: + try: + data[uuid] = await self.client.read_char_raw(uuid) + except CharacteristicNoAccess as exception: + LOGGER.debug("Unable to get data for %s due to %s", uuid, exception) + except (GardenaBluetoothException, DeviceUnavailable) as exception: + raise UpdateFailed( + f"Unable to update data for {uuid} due to {exception}" + ) from exception + return data + + def read_cached( + self, char: Characteristic[CharacteristicType] + ) -> CharacteristicType | None: + """Read cached characteristic.""" + if data := self.data.get(char.uuid): + return char.decode(data) + return None + + async def write( + self, char: Characteristic[CharacteristicType], value: CharacteristicType + ) -> None: + """Write characteristic to device.""" + try: + await self.client.write_char(char, value) + except (GardenaBluetoothException, DeviceUnavailable) as exception: + raise HomeAssistantError( + f"Unable to write characteristic {char} dur to {exception}" + ) from exception + + self.data[char.uuid] = char.encode(value) + await self.async_refresh() + + +class GardenaBluetoothEntity(CoordinatorEntity[Coordinator]): + """Coordinator entity for Gardena Bluetooth.""" + + _attr_has_entity_name = True + + def __init__(self, coordinator: Coordinator, context: Any = None) -> None: + """Initialize coordinator entity.""" + super().__init__(coordinator, context) + self._attr_device_info = coordinator.device_info + + @property + def available(self) -> bool: + """Return if entity is available.""" + return super().available and bluetooth.async_address_present( + self.hass, self.coordinator.address, True + ) diff --git a/homeassistant/components/gardena_bluetooth/manifest.json b/homeassistant/components/gardena_bluetooth/manifest.json new file mode 100644 index 00000000000000..cdc43a802c99c7 --- /dev/null +++ b/homeassistant/components/gardena_bluetooth/manifest.json @@ -0,0 +1,17 @@ +{ + "domain": "gardena_bluetooth", + "name": "Gardena Bluetooth", + "bluetooth": [ + { + "manufacturer_id": 1062, + "service_uuid": "98bd0001-0b0e-421a-84e5-ddbf75dc6de4", + "connectable": true + } + ], + "codeowners": ["@elupus"], + "config_flow": true, + "dependencies": ["bluetooth_adapters"], + "documentation": "https://www.home-assistant.io/integrations/gardena_bluetooth", + "iot_class": "local_polling", + "requirements": ["gardena_bluetooth==1.0.1"] +} diff --git a/homeassistant/components/gardena_bluetooth/strings.json b/homeassistant/components/gardena_bluetooth/strings.json new file mode 100644 index 00000000000000..165e336bbecb60 --- /dev/null +++ b/homeassistant/components/gardena_bluetooth/strings.json @@ -0,0 +1,28 @@ +{ + "config": { + "step": { + "user": { + "description": "[%key:component::bluetooth::config::step::user::description%]", + "data": { + "address": "[%key:component::bluetooth::config::step::user::data::address%]" + } + }, + "confirm": { + "description": "[%key:component::bluetooth::config::step::bluetooth_confirm::description%]" + } + }, + "error": { + "cannot_connect": "Failed to connect: {error}" + }, + "abort": { + "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" + } + }, + "entity": { + "switch": { + "state": { + "name": "Open" + } + } + } +} diff --git a/homeassistant/components/gardena_bluetooth/switch.py b/homeassistant/components/gardena_bluetooth/switch.py new file mode 100644 index 00000000000000..e3fcc8978c7683 --- /dev/null +++ b/homeassistant/components/gardena_bluetooth/switch.py @@ -0,0 +1,74 @@ +"""Support for switch entities.""" +from __future__ import annotations + +from typing import Any + +from gardena_bluetooth.const import Valve + +from homeassistant.components.switch import SwitchEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from .const import DOMAIN +from .coordinator import Coordinator, GardenaBluetoothEntity + + +async def async_setup_entry( + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback +) -> None: + """Set up switch based on a config entry.""" + coordinator: Coordinator = hass.data[DOMAIN][entry.entry_id] + entities = [] + if GardenaBluetoothValveSwitch.characteristics.issubset( + coordinator.characteristics + ): + entities.append(GardenaBluetoothValveSwitch(coordinator)) + + async_add_entities(entities) + + +class GardenaBluetoothValveSwitch(GardenaBluetoothEntity, SwitchEntity): + """Representation of a valve switch.""" + + characteristics = { + Valve.state.uuid, + Valve.manual_watering_time.uuid, + Valve.manual_watering_time.uuid, + } + + def __init__( + self, + coordinator: Coordinator, + ) -> None: + """Initialize the switch.""" + super().__init__( + coordinator, {Valve.state.uuid, Valve.manual_watering_time.uuid} + ) + self._attr_unique_id = f"{coordinator.address}-{Valve.state.uuid}" + self._attr_translation_key = "state" + self._attr_is_on = None + + def _handle_coordinator_update(self) -> None: + if data := self.coordinator.data.get(Valve.state.uuid): + self._attr_is_on = Valve.state.decode(data) + else: + self._attr_is_on = None + super()._handle_coordinator_update() + + async def async_turn_on(self, **kwargs: Any) -> None: + """Turn the entity on.""" + if not (data := self.coordinator.data.get(Valve.manual_watering_time.uuid)): + raise HomeAssistantError("Unable to get manual activation time.") + + value = Valve.manual_watering_time.decode(data) + await self.coordinator.write(Valve.remaining_open_time, value) + self._attr_is_on = True + self.async_write_ha_state() + + async def async_turn_off(self, **kwargs: Any) -> None: + """Turn the entity off.""" + await self.coordinator.write(Valve.remaining_open_time, 0) + self._attr_is_on = False + self.async_write_ha_state() diff --git a/homeassistant/generated/bluetooth.py b/homeassistant/generated/bluetooth.py index 24215a8a0c4d50..64fae252975a66 100644 --- a/homeassistant/generated/bluetooth.py +++ b/homeassistant/generated/bluetooth.py @@ -83,6 +83,12 @@ ], "manufacturer_id": 20296, }, + { + "connectable": True, + "domain": "gardena_bluetooth", + "manufacturer_id": 1062, + "service_uuid": "98bd0001-0b0e-421a-84e5-ddbf75dc6de4", + }, { "connectable": False, "domain": "govee_ble", diff --git a/homeassistant/generated/config_flows.py b/homeassistant/generated/config_flows.py index d8ffa25b765da0..6d9a132a29a8eb 100644 --- a/homeassistant/generated/config_flows.py +++ b/homeassistant/generated/config_flows.py @@ -155,6 +155,7 @@ "frontier_silicon", "fully_kiosk", "garages_amsterdam", + "gardena_bluetooth", "gdacs", "generic", "geo_json_events", diff --git a/homeassistant/generated/integrations.json b/homeassistant/generated/integrations.json index d1f68271c55169..21f7acd59e39c0 100644 --- a/homeassistant/generated/integrations.json +++ b/homeassistant/generated/integrations.json @@ -1884,6 +1884,12 @@ "config_flow": true, "iot_class": "cloud_polling" }, + "gardena_bluetooth": { + "name": "Gardena Bluetooth", + "integration_type": "hub", + "config_flow": true, + "iot_class": "local_polling" + }, "gaviota": { "name": "Gaviota", "integration_type": "virtual", diff --git a/requirements_all.txt b/requirements_all.txt index 0cb289d748fb75..d33f01b34be376 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -819,6 +819,9 @@ fritzconnection[qr]==1.12.2 # homeassistant.components.google_translate gTTS==2.2.4 +# homeassistant.components.gardena_bluetooth +gardena_bluetooth==1.0.1 + # homeassistant.components.google_assistant_sdk gassist-text==0.0.10 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 04065df19c1307..f35021c3e006af 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -641,6 +641,9 @@ fritzconnection[qr]==1.12.2 # homeassistant.components.google_translate gTTS==2.2.4 +# homeassistant.components.gardena_bluetooth +gardena_bluetooth==1.0.1 + # homeassistant.components.google_assistant_sdk gassist-text==0.0.10 diff --git a/tests/components/gardena_bluetooth/__init__.py b/tests/components/gardena_bluetooth/__init__.py new file mode 100644 index 00000000000000..6a064409e9e2f3 --- /dev/null +++ b/tests/components/gardena_bluetooth/__init__.py @@ -0,0 +1,61 @@ +"""Tests for the Gardena Bluetooth integration.""" + +from homeassistant.helpers.service_info.bluetooth import BluetoothServiceInfo + +WATER_TIMER_SERVICE_INFO = BluetoothServiceInfo( + name="Timer", + address="00000000-0000-0000-0000-000000000001", + rssi=-63, + service_data={}, + manufacturer_data={ + 1062: b"\x02\x07d\x02\x05\x01\x02\x08\x00\x02\t\x01\x04\x06\x12\x00\x01" + }, + service_uuids=["98bd0001-0b0e-421a-84e5-ddbf75dc6de4"], + source="local", +) + +WATER_TIMER_UNNAMED_SERVICE_INFO = BluetoothServiceInfo( + name=None, + address="00000000-0000-0000-0000-000000000002", + rssi=-63, + service_data={}, + manufacturer_data={ + 1062: b"\x02\x07d\x02\x05\x01\x02\x08\x00\x02\t\x01\x04\x06\x12\x00\x01" + }, + service_uuids=["98bd0001-0b0e-421a-84e5-ddbf75dc6de4"], + source="local", +) + +MISSING_SERVICE_SERVICE_INFO = BluetoothServiceInfo( + name="Missing Service Info", + address="00000000-0000-0000-0001-000000000000", + rssi=-63, + service_data={}, + manufacturer_data={ + 1062: b"\x02\x07d\x02\x05\x01\x02\x08\x00\x02\t\x01\x04\x06\x12\x00\x01" + }, + service_uuids=[], + source="local", +) + +MISSING_MANUFACTURER_DATA_SERVICE_INFO = BluetoothServiceInfo( + name="Missing Manufacturer Data", + address="00000000-0000-0000-0001-000000000001", + rssi=-63, + service_data={}, + manufacturer_data={}, + service_uuids=["98bd0001-0b0e-421a-84e5-ddbf75dc6de4"], + source="local", +) + +UNSUPPORTED_GROUP_SERVICE_INFO = BluetoothServiceInfo( + name="Unsupported Group", + address="00000000-0000-0000-0001-000000000002", + rssi=-63, + service_data={}, + manufacturer_data={ + 1062: b"\x02\x07d\x02\x05\x01\x02\x08\x00\x02\t\x01\x04\x06\x10\x00\x01" + }, + service_uuids=["98bd0001-0b0e-421a-84e5-ddbf75dc6de4"], + source="local", +) diff --git a/tests/components/gardena_bluetooth/conftest.py b/tests/components/gardena_bluetooth/conftest.py new file mode 100644 index 00000000000000..f09a274742f617 --- /dev/null +++ b/tests/components/gardena_bluetooth/conftest.py @@ -0,0 +1,30 @@ +"""Common fixtures for the Gardena Bluetooth tests.""" +from collections.abc import Generator +from unittest.mock import AsyncMock, Mock, patch + +from gardena_bluetooth.client import Client +import pytest + + +@pytest.fixture +def mock_setup_entry() -> Generator[AsyncMock, None, None]: + """Override async_setup_entry.""" + with patch( + "homeassistant.components.gardena_bluetooth.async_setup_entry", + return_value=True, + ) as mock_setup_entry: + yield mock_setup_entry + + +@pytest.fixture(autouse=True) +def mock_client(enable_bluetooth): + """Auto mock bluetooth.""" + + client = Mock(spec_set=Client) + client.get_all_characteristics_uuid.return_value = set() + + with patch( + "homeassistant.components.gardena_bluetooth.config_flow.Client", + return_value=client, + ): + yield client diff --git a/tests/components/gardena_bluetooth/snapshots/test_config_flow.ambr b/tests/components/gardena_bluetooth/snapshots/test_config_flow.ambr new file mode 100644 index 00000000000000..fde70b60a01d39 --- /dev/null +++ b/tests/components/gardena_bluetooth/snapshots/test_config_flow.ambr @@ -0,0 +1,258 @@ +# serializer version: 1 +# name: test_bluetooth + FlowResultSnapshot({ + 'data_schema': None, + 'description_placeholders': dict({ + 'name': 'Timer', + }), + 'errors': None, + 'flow_id': , + 'handler': 'gardena_bluetooth', + 'last_step': None, + 'step_id': 'confirm', + 'type': , + }) +# --- +# name: test_bluetooth.1 + FlowResultSnapshot({ + 'context': dict({ + 'confirm_only': True, + 'source': 'bluetooth', + 'title_placeholders': dict({ + 'name': 'Timer', + }), + 'unique_id': '00000000-0000-0000-0000-000000000001', + }), + 'data': dict({ + 'address': '00000000-0000-0000-0000-000000000001', + }), + 'description': None, + 'description_placeholders': None, + 'flow_id': , + 'handler': 'gardena_bluetooth', + 'options': dict({ + }), + 'result': ConfigEntrySnapshot({ + 'data': dict({ + 'address': '00000000-0000-0000-0000-000000000001', + }), + 'disabled_by': None, + 'domain': 'gardena_bluetooth', + 'entry_id': , + 'options': dict({ + }), + 'pref_disable_new_entities': False, + 'pref_disable_polling': False, + 'source': 'bluetooth', + 'title': 'Timer', + 'unique_id': '00000000-0000-0000-0000-000000000001', + 'version': 1, + }), + 'title': 'Timer', + 'type': , + 'version': 1, + }) +# --- +# name: test_bluetooth_invalid + FlowResultSnapshot({ + 'description_placeholders': None, + 'flow_id': , + 'handler': 'gardena_bluetooth', + 'reason': 'no_devices_found', + 'type': , + }) +# --- +# name: test_bluetooth_lost + FlowResultSnapshot({ + 'data_schema': None, + 'description_placeholders': dict({ + 'name': 'Timer', + }), + 'errors': None, + 'flow_id': , + 'handler': 'gardena_bluetooth', + 'last_step': None, + 'step_id': 'confirm', + 'type': , + }) +# --- +# name: test_bluetooth_lost.1 + FlowResultSnapshot({ + 'context': dict({ + 'confirm_only': True, + 'source': 'bluetooth', + 'title_placeholders': dict({ + 'name': 'Timer', + }), + 'unique_id': '00000000-0000-0000-0000-000000000001', + }), + 'data': dict({ + 'address': '00000000-0000-0000-0000-000000000001', + }), + 'description': None, + 'description_placeholders': None, + 'flow_id': , + 'handler': 'gardena_bluetooth', + 'options': dict({ + }), + 'result': ConfigEntrySnapshot({ + 'data': dict({ + 'address': '00000000-0000-0000-0000-000000000001', + }), + 'disabled_by': None, + 'domain': 'gardena_bluetooth', + 'entry_id': , + 'options': dict({ + }), + 'pref_disable_new_entities': False, + 'pref_disable_polling': False, + 'source': 'bluetooth', + 'title': 'Timer', + 'unique_id': '00000000-0000-0000-0000-000000000001', + 'version': 1, + }), + 'title': 'Timer', + 'type': , + 'version': 1, + }) +# --- +# name: test_failed_connect + FlowResultSnapshot({ + 'data_schema': list([ + dict({ + 'name': 'address', + 'options': list([ + tuple( + '00000000-0000-0000-0000-000000000001', + 'Timer', + ), + ]), + 'required': True, + 'type': 'select', + }), + ]), + 'description_placeholders': None, + 'errors': None, + 'flow_id': , + 'handler': 'gardena_bluetooth', + 'last_step': None, + 'step_id': 'user', + 'type': , + }) +# --- +# name: test_failed_connect.1 + FlowResultSnapshot({ + 'data_schema': None, + 'description_placeholders': dict({ + 'name': 'Timer', + }), + 'errors': None, + 'flow_id': , + 'handler': 'gardena_bluetooth', + 'last_step': None, + 'step_id': 'confirm', + 'type': , + }) +# --- +# name: test_failed_connect.2 + FlowResultSnapshot({ + 'description_placeholders': dict({ + 'error': 'something went wrong', + }), + 'flow_id': , + 'handler': 'gardena_bluetooth', + 'reason': 'cannot_connect', + 'type': , + }) +# --- +# name: test_no_devices + FlowResultSnapshot({ + 'description_placeholders': None, + 'flow_id': , + 'handler': 'gardena_bluetooth', + 'reason': 'no_devices_found', + 'type': , + }) +# --- +# name: test_user_selection + FlowResultSnapshot({ + 'data_schema': list([ + dict({ + 'name': 'address', + 'options': list([ + tuple( + '00000000-0000-0000-0000-000000000001', + 'Timer', + ), + tuple( + '00000000-0000-0000-0000-000000000002', + 'Gardena Device', + ), + ]), + 'required': True, + 'type': 'select', + }), + ]), + 'description_placeholders': None, + 'errors': None, + 'flow_id': , + 'handler': 'gardena_bluetooth', + 'last_step': None, + 'step_id': 'user', + 'type': , + }) +# --- +# name: test_user_selection.1 + FlowResultSnapshot({ + 'data_schema': None, + 'description_placeholders': dict({ + 'name': 'Timer', + }), + 'errors': None, + 'flow_id': , + 'handler': 'gardena_bluetooth', + 'last_step': None, + 'step_id': 'confirm', + 'type': , + }) +# --- +# name: test_user_selection.2 + FlowResultSnapshot({ + 'context': dict({ + 'confirm_only': True, + 'source': 'user', + 'title_placeholders': dict({ + 'name': 'Timer', + }), + 'unique_id': '00000000-0000-0000-0000-000000000001', + }), + 'data': dict({ + 'address': '00000000-0000-0000-0000-000000000001', + }), + 'description': None, + 'description_placeholders': None, + 'flow_id': , + 'handler': 'gardena_bluetooth', + 'options': dict({ + }), + 'result': ConfigEntrySnapshot({ + 'data': dict({ + 'address': '00000000-0000-0000-0000-000000000001', + }), + 'disabled_by': None, + 'domain': 'gardena_bluetooth', + 'entry_id': , + 'options': dict({ + }), + 'pref_disable_new_entities': False, + 'pref_disable_polling': False, + 'source': 'user', + 'title': 'Timer', + 'unique_id': '00000000-0000-0000-0000-000000000001', + 'version': 1, + }), + 'title': 'Timer', + 'type': , + 'version': 1, + }) +# --- diff --git a/tests/components/gardena_bluetooth/test_config_flow.py b/tests/components/gardena_bluetooth/test_config_flow.py new file mode 100644 index 00000000000000..0f0e297c4d7fa6 --- /dev/null +++ b/tests/components/gardena_bluetooth/test_config_flow.py @@ -0,0 +1,134 @@ +"""Test the Gardena Bluetooth config flow.""" +from unittest.mock import Mock + +from gardena_bluetooth.exceptions import CharacteristicNotFound +import pytest +from syrupy.assertion import SnapshotAssertion + +from homeassistant import config_entries +from homeassistant.components.gardena_bluetooth.const import DOMAIN +from homeassistant.core import HomeAssistant + +from . import ( + MISSING_MANUFACTURER_DATA_SERVICE_INFO, + MISSING_SERVICE_SERVICE_INFO, + UNSUPPORTED_GROUP_SERVICE_INFO, + WATER_TIMER_SERVICE_INFO, + WATER_TIMER_UNNAMED_SERVICE_INFO, +) + +from tests.components.bluetooth import ( + inject_bluetooth_service_info, +) + +pytestmark = pytest.mark.usefixtures("mock_setup_entry") + + +async def test_user_selection( + hass: HomeAssistant, + snapshot: SnapshotAssertion, +) -> None: + """Test we can select a device.""" + + inject_bluetooth_service_info(hass, WATER_TIMER_SERVICE_INFO) + inject_bluetooth_service_info(hass, WATER_TIMER_UNNAMED_SERVICE_INFO) + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} + ) + assert result == snapshot + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={"address": "00000000-0000-0000-0000-000000000001"}, + ) + assert result == snapshot + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={}, + ) + assert result == snapshot + + +async def test_failed_connect( + hass: HomeAssistant, + mock_client: Mock, + snapshot: SnapshotAssertion, +) -> None: + """Test we can select a device.""" + + inject_bluetooth_service_info(hass, WATER_TIMER_SERVICE_INFO) + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} + ) + assert result == snapshot + + mock_client.read_char.side_effect = CharacteristicNotFound("something went wrong") + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={"address": "00000000-0000-0000-0000-000000000001"}, + ) + assert result == snapshot + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={}, + ) + assert result == snapshot + + +async def test_no_devices( + hass: HomeAssistant, + snapshot: SnapshotAssertion, +) -> None: + """Test missing device.""" + + inject_bluetooth_service_info(hass, MISSING_MANUFACTURER_DATA_SERVICE_INFO) + inject_bluetooth_service_info(hass, MISSING_SERVICE_SERVICE_INFO) + inject_bluetooth_service_info(hass, UNSUPPORTED_GROUP_SERVICE_INFO) + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} + ) + assert result == snapshot + + +async def test_bluetooth( + hass: HomeAssistant, + snapshot: SnapshotAssertion, +) -> None: + """Test bluetooth device discovery.""" + + inject_bluetooth_service_info(hass, WATER_TIMER_SERVICE_INFO) + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_BLUETOOTH}, + data=WATER_TIMER_SERVICE_INFO, + ) + assert result == snapshot + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={}, + ) + assert result == snapshot + + +async def test_bluetooth_invalid( + hass: HomeAssistant, + snapshot: SnapshotAssertion, +) -> None: + """Test bluetooth device discovery with invalid data.""" + + inject_bluetooth_service_info(hass, UNSUPPORTED_GROUP_SERVICE_INFO) + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_BLUETOOTH}, + data=UNSUPPORTED_GROUP_SERVICE_INFO, + ) + assert result == snapshot From c236d1734366bda28f1d2fc64b685885f7fde2fc Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 16:10:32 +0200 Subject: [PATCH 090/154] Migrate cover services to support translations (#96315) * Migrate cover services to support translations * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/cover/services.yaml | 24 --------- homeassistant/components/cover/strings.json | 54 ++++++++++++++++++++ 2 files changed, 54 insertions(+), 24 deletions(-) diff --git a/homeassistant/components/cover/services.yaml b/homeassistant/components/cover/services.yaml index 8ab42c6d3e97c5..9f9e37941e2ccb 100644 --- a/homeassistant/components/cover/services.yaml +++ b/homeassistant/components/cover/services.yaml @@ -1,8 +1,6 @@ # Describes the format for available cover services open_cover: - name: Open - description: Open all or specified cover. target: entity: domain: cover @@ -10,8 +8,6 @@ open_cover: - cover.CoverEntityFeature.OPEN close_cover: - name: Close - description: Close all or specified cover. target: entity: domain: cover @@ -19,8 +15,6 @@ close_cover: - cover.CoverEntityFeature.CLOSE toggle: - name: Toggle - description: Toggle a cover open/closed. target: entity: domain: cover @@ -29,8 +23,6 @@ toggle: - cover.CoverEntityFeature.OPEN set_cover_position: - name: Set position - description: Move to specific position all or specified cover. target: entity: domain: cover @@ -38,8 +30,6 @@ set_cover_position: - cover.CoverEntityFeature.SET_POSITION fields: position: - name: Position - description: Position of the cover required: true selector: number: @@ -48,8 +38,6 @@ set_cover_position: unit_of_measurement: "%" stop_cover: - name: Stop - description: Stop all or specified cover. target: entity: domain: cover @@ -57,8 +45,6 @@ stop_cover: - cover.CoverEntityFeature.STOP open_cover_tilt: - name: Open tilt - description: Open all or specified cover tilt. target: entity: domain: cover @@ -66,8 +52,6 @@ open_cover_tilt: - cover.CoverEntityFeature.OPEN_TILT close_cover_tilt: - name: Close tilt - description: Close all or specified cover tilt. target: entity: domain: cover @@ -75,8 +59,6 @@ close_cover_tilt: - cover.CoverEntityFeature.CLOSE_TILT toggle_cover_tilt: - name: Toggle tilt - description: Toggle a cover tilt open/closed. target: entity: domain: cover @@ -85,8 +67,6 @@ toggle_cover_tilt: - cover.CoverEntityFeature.OPEN_TILT set_cover_tilt_position: - name: Set tilt position - description: Move to specific position all or specified cover tilt. target: entity: domain: cover @@ -94,8 +74,6 @@ set_cover_tilt_position: - cover.CoverEntityFeature.SET_TILT_POSITION fields: tilt_position: - name: Tilt position - description: Tilt position of the cover. required: true selector: number: @@ -104,8 +82,6 @@ set_cover_tilt_position: unit_of_measurement: "%" stop_cover_tilt: - name: Stop tilt - description: Stop all or specified cover. target: entity: domain: cover diff --git a/homeassistant/components/cover/strings.json b/homeassistant/components/cover/strings.json index 2f61bd95083e94..5ed02a84e0df7d 100644 --- a/homeassistant/components/cover/strings.json +++ b/homeassistant/components/cover/strings.json @@ -76,5 +76,59 @@ "window": { "name": "Window" } + }, + "services": { + "open_cover": { + "name": "Open", + "description": "Opens a cover." + }, + "close_cover": { + "name": "Close", + "description": "Closes a cover." + }, + "toggle": { + "name": "Toggle", + "description": "Toggles a cover open/closed." + }, + "set_cover_position": { + "name": "Set position", + "description": "Moves a cover to a specific position.", + "fields": { + "position": { + "name": "Position", + "description": "Target position." + } + } + }, + "stop_cover": { + "name": "Stop", + "description": "Stops the cover movement." + }, + "open_cover_tilt": { + "name": "Open tilt", + "description": "Tilts a cover open." + }, + "close_cover_tilt": { + "name": "Close tilt", + "description": "Tilts a cover to close." + }, + "toggle_cover_tilt": { + "name": "Toggle tilt", + "description": "Toggles a cover tilt open/closed." + }, + "set_cover_tilt_position": { + "name": "Set tilt position", + "description": "Moves a cover tilt to a specific position.", + "fields": { + "tilt_position": { + "name": "Tilt position", + "description": "Target tilt positition." + } + } + }, + "stop_cover_tilt": { + "name": "Stop tilt", + "description": "Stops a tilting cover movement." + } } } From 2d474813c01a7ed0ec52289bacb67e44839862b4 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 16:11:01 +0200 Subject: [PATCH 091/154] Migrate siren services to support translations (#96400) * Migrate siren services to support translations * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/siren/services.yaml | 9 ------- homeassistant/components/siren/strings.json | 28 ++++++++++++++++++++ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/siren/services.yaml b/homeassistant/components/siren/services.yaml index 154ffff78a3a12..4c2f612bcbc98f 100644 --- a/homeassistant/components/siren/services.yaml +++ b/homeassistant/components/siren/services.yaml @@ -1,8 +1,6 @@ # Describes the format for available siren services turn_on: - name: Turn on - description: Turn siren on. target: entity: domain: siren @@ -10,7 +8,6 @@ turn_on: - siren.SirenEntityFeature.TURN_ON fields: tone: - description: The tone to emit when turning the siren on. When `available_tones` property is a map, either the key or the value can be used. Must be supported by the integration. example: fire filter: supported_features: @@ -19,7 +16,6 @@ turn_on: selector: text: volume_level: - description: The volume level of the noise to emit when turning the siren on. Must be supported by the integration. example: 0.5 filter: supported_features: @@ -31,7 +27,6 @@ turn_on: max: 1 step: 0.05 duration: - description: The duration in seconds of the noise to emit when turning the siren on. Must be supported by the integration. example: 15 filter: supported_features: @@ -41,8 +36,6 @@ turn_on: text: turn_off: - name: Turn off - description: Turn siren off. target: entity: domain: siren @@ -50,8 +43,6 @@ turn_off: - siren.SirenEntityFeature.TURN_OFF toggle: - name: Toggle - description: Toggles a siren. target: entity: domain: siren diff --git a/homeassistant/components/siren/strings.json b/homeassistant/components/siren/strings.json index 60d8843c1515e5..171a853f74c2fe 100644 --- a/homeassistant/components/siren/strings.json +++ b/homeassistant/components/siren/strings.json @@ -13,5 +13,33 @@ } } } + }, + "services": { + "turn_on": { + "name": "Turn on", + "description": "Turns the siren on.", + "fields": { + "tone": { + "name": "Tone", + "description": "The tone to emit. When `available_tones` property is a map, either the key or the value can be used. Must be supported by the integration." + }, + "volume_level": { + "name": "Volume", + "description": "The volume. 0 is inaudible, 1 is the maximum volume. Must be supported by the integration." + }, + "duration": { + "name": "Duration", + "description": "Number of seconds the sound is played. Must be supported by the integration." + } + } + }, + "turn_off": { + "name": "Turn off", + "description": "Turns the siren off." + }, + "toggle": { + "name": "Toggle", + "description": "Toggles the siren on/off." + } } } From 7ca539fcd041cc1cd22e13254e88b375013f663e Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 16:11:28 +0200 Subject: [PATCH 092/154] Migrate persistent notification services to support translations (#96391) * Migrate persistent notification services to support translations * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- .../persistent_notification/services.yaml | 14 -------- .../persistent_notification/strings.json | 36 +++++++++++++++++++ 2 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 homeassistant/components/persistent_notification/strings.json diff --git a/homeassistant/components/persistent_notification/services.yaml b/homeassistant/components/persistent_notification/services.yaml index 046ea237560233..c335d96260087d 100644 --- a/homeassistant/components/persistent_notification/services.yaml +++ b/homeassistant/components/persistent_notification/services.yaml @@ -1,39 +1,25 @@ create: - name: Create - description: Show a notification in the frontend. fields: message: - name: Message - description: Message body of the notification. required: true example: Please check your configuration.yaml. selector: text: title: - name: Title - description: Optional title for your notification. example: Test notification selector: text: notification_id: - name: Notification ID - description: Target ID of the notification, will replace a notification with the same ID. example: 1234 selector: text: dismiss: - name: Dismiss - description: Remove a notification from the frontend. fields: notification_id: - name: Notification ID - description: Target ID of the notification, which should be removed. required: true example: 1234 selector: text: dismiss_all: - name: Dismiss All - description: Remove all notifications. diff --git a/homeassistant/components/persistent_notification/strings.json b/homeassistant/components/persistent_notification/strings.json new file mode 100644 index 00000000000000..6b8ddb46c497be --- /dev/null +++ b/homeassistant/components/persistent_notification/strings.json @@ -0,0 +1,36 @@ +{ + "services": { + "create": { + "name": "Create", + "description": "Shows a notification on the **Notifications** panel.", + "fields": { + "message": { + "name": "Message", + "description": "Message body of the notification." + }, + "title": { + "name": "Title", + "description": "Optional title of the notification." + }, + "notification_id": { + "name": "Notification ID", + "description": "ID of the notification. This new notification will overwrite an existing notification with the same ID." + } + } + }, + "dismiss": { + "name": "Dismiss", + "description": "Removes a notification from the **Notifications** panel.", + "fields": { + "notification_id": { + "name": "Notification ID", + "description": "ID of the notification to be removed." + } + } + }, + "dismiss_all": { + "name": "Dismiss all", + "description": "Removes all notifications from the **Notifications** panel." + } + } +} From 18cc56ae96c0e630fd3185275ad085e789574412 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 16:25:43 +0200 Subject: [PATCH 093/154] Migrate media player services to support translations (#96408) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- .../components/media_player/services.yaml | 98 +--------- .../components/media_player/strings.json | 173 ++++++++++++++++++ 2 files changed, 182 insertions(+), 89 deletions(-) diff --git a/homeassistant/components/media_player/services.yaml b/homeassistant/components/media_player/services.yaml index 97605886036a27..7338747b545a03 100644 --- a/homeassistant/components/media_player/services.yaml +++ b/homeassistant/components/media_player/services.yaml @@ -1,8 +1,6 @@ # Describes the format for available media player services turn_on: - name: Turn on - description: Turn a media player power on. target: entity: domain: media_player @@ -10,8 +8,6 @@ turn_on: - media_player.MediaPlayerEntityFeature.TURN_ON turn_off: - name: Turn off - description: Turn a media player power off. target: entity: domain: media_player @@ -19,8 +15,6 @@ turn_off: - media_player.MediaPlayerEntityFeature.TURN_OFF toggle: - name: Toggle - description: Toggles a media player power state. target: entity: domain: media_player @@ -29,8 +23,6 @@ toggle: - media_player.MediaPlayerEntityFeature.TURN_ON volume_up: - name: Turn up volume - description: Turn a media player volume up. target: entity: domain: media_player @@ -39,8 +31,6 @@ volume_up: - media_player.MediaPlayerEntityFeature.VOLUME_STEP volume_down: - name: Turn down volume - description: Turn a media player volume down. target: entity: domain: media_player @@ -49,8 +39,6 @@ volume_down: - media_player.MediaPlayerEntityFeature.VOLUME_STEP volume_mute: - name: Mute volume - description: Mute a media player's volume. target: entity: domain: media_player @@ -58,15 +46,11 @@ volume_mute: - media_player.MediaPlayerEntityFeature.VOLUME_MUTE fields: is_volume_muted: - name: Muted - description: True/false for mute/unmute. required: true selector: boolean: volume_set: - name: Set volume - description: Set a media player's volume level. target: entity: domain: media_player @@ -74,8 +58,6 @@ volume_set: - media_player.MediaPlayerEntityFeature.VOLUME_SET fields: volume_level: - name: Level - description: Volume level to set as float. required: true selector: number: @@ -84,8 +66,6 @@ volume_set: step: 0.01 media_play_pause: - name: Play/Pause - description: Toggle media player play/pause state. target: entity: domain: media_player @@ -94,8 +74,6 @@ media_play_pause: - media_player.MediaPlayerEntityFeature.PLAY media_play: - name: Play - description: Send the media player the command for play. target: entity: domain: media_player @@ -103,8 +81,6 @@ media_play: - media_player.MediaPlayerEntityFeature.PLAY media_pause: - name: Pause - description: Send the media player the command for pause. target: entity: domain: media_player @@ -112,8 +88,6 @@ media_pause: - media_player.MediaPlayerEntityFeature.PAUSE media_stop: - name: Stop - description: Send the media player the stop command. target: entity: domain: media_player @@ -121,8 +95,6 @@ media_stop: - media_player.MediaPlayerEntityFeature.STOP media_next_track: - name: Next - description: Send the media player the command for next track. target: entity: domain: media_player @@ -130,8 +102,6 @@ media_next_track: - media_player.MediaPlayerEntityFeature.NEXT_TRACK media_previous_track: - name: Previous - description: Send the media player the command for previous track. target: entity: domain: media_player @@ -139,8 +109,6 @@ media_previous_track: - media_player.MediaPlayerEntityFeature.PREVIOUS_TRACK media_seek: - name: Seek - description: Send the media player the command to seek in current playing media. target: entity: domain: media_player @@ -148,8 +116,6 @@ media_seek: - media_player.MediaPlayerEntityFeature.SEEK fields: seek_position: - name: Position - description: Position to seek to. The format is platform dependent. required: true selector: number: @@ -159,8 +125,6 @@ media_seek: mode: box play_media: - name: Play media - description: Send the media player the command for playing media. target: entity: domain: media_player @@ -168,26 +132,18 @@ play_media: - media_player.MediaPlayerEntityFeature.PLAY_MEDIA fields: media_content_id: - name: Content ID - description: The ID of the content to play. Platform dependent. required: true example: "https://home-assistant.io/images/cast/splash.png" selector: text: media_content_type: - name: Content type - description: - The type of the content to play. Like image, music, tvshow, video, - episode, channel or playlist. required: true example: "music" selector: text: enqueue: - name: Enqueue - description: If the content should be played now or be added to the queue. filter: supported_features: - media_player.MediaPlayerEntityFeature.MEDIA_ENQUEUE @@ -195,17 +151,12 @@ play_media: selector: select: options: - - label: "Play now" - value: "play" - - label: "Play next" - value: "next" - - label: "Add to queue" - value: "add" - - label: "Play now and clear queue" - value: "replace" + - "play" + - "next" + - "add" + - "replace" + translation_key: enqueue announce: - name: Announce - description: If the media should be played as an announcement. filter: supported_features: - media_player.MediaPlayerEntityFeature.MEDIA_ANNOUNCE @@ -215,8 +166,6 @@ play_media: boolean: select_source: - name: Select source - description: Send the media player the command to change input source. target: entity: domain: media_player @@ -224,16 +173,12 @@ select_source: - media_player.MediaPlayerEntityFeature.SELECT_SOURCE fields: source: - name: Source - description: Name of the source to switch to. Platform dependent. required: true example: "video1" selector: text: select_sound_mode: - name: Select sound mode - description: Send the media player the command to change sound mode. target: entity: domain: media_player @@ -241,15 +186,11 @@ select_sound_mode: - media_player.MediaPlayerEntityFeature.SELECT_SOUND_MODE fields: sound_mode: - name: Sound mode - description: Name of the sound mode to switch to. example: "Music" selector: text: clear_playlist: - name: Clear playlist - description: Send the media player the command to clear players playlist. target: entity: domain: media_player @@ -257,8 +198,6 @@ clear_playlist: - media_player.MediaPlayerEntityFeature.CLEAR_PLAYLIST shuffle_set: - name: Shuffle - description: Set shuffling state. target: entity: domain: media_player @@ -266,15 +205,11 @@ shuffle_set: - media_player.MediaPlayerEntityFeature.SHUFFLE_SET fields: shuffle: - name: Shuffle - description: True/false for enabling/disabling shuffle. required: true selector: boolean: repeat_set: - name: Repeat - description: Set repeat mode target: entity: domain: media_player @@ -282,24 +217,15 @@ repeat_set: - media_player.MediaPlayerEntityFeature.REPEAT_SET fields: repeat: - name: Repeat mode - description: Repeat mode to set. required: true selector: select: options: - - label: "Off" - value: "off" - - label: "Repeat all" - value: "all" - - label: "Repeat one" - value: "one" - + - "off" + - "all" + - "one" + translation_key: repeat join: - name: Join - description: - Group players together. Only works on platforms with support for player - groups. target: entity: domain: media_player @@ -307,8 +233,6 @@ join: - media_player.MediaPlayerEntityFeature.GROUPING fields: group_members: - name: Group members - description: The players which will be synced with the target player. required: true example: | - media_player.multiroom_player2 @@ -319,10 +243,6 @@ join: domain: media_player unjoin: - description: - Unjoin the player from a group. Only works on platforms with support for - player groups. - name: Unjoin target: entity: domain: media_player diff --git a/homeassistant/components/media_player/strings.json b/homeassistant/components/media_player/strings.json index 67c92d7ce072f3..10148f99fef52c 100644 --- a/homeassistant/components/media_player/strings.json +++ b/homeassistant/components/media_player/strings.json @@ -159,5 +159,178 @@ "receiver": { "name": "Receiver" } + }, + "services": { + "turn_on": { + "name": "Turn on", + "description": "Turns on the power of the media player." + }, + "turn_off": { + "name": "Turn off", + "description": "Turns off the power of the media player." + }, + "toggle": { + "name": "Toggle", + "description": "Toggles a media player on/off." + }, + "volume_up": { + "name": "Turn up volume", + "description": "Turns up the volume." + }, + "volume_down": { + "name": "Turn down volume", + "description": "Turns down the volume." + }, + "volume_mute": { + "name": "Mute/unmute volume", + "description": "Mutes or unmutes the media player.", + "fields": { + "is_volume_muted": { + "name": "Muted", + "description": "Defines whether or not it is muted." + } + } + }, + "volume_set": { + "name": "Set volume", + "description": "Sets the volume level.", + "fields": { + "volume_level": { + "name": "Level", + "description": "The volume. 0 is inaudible, 1 is the maximum volume." + } + } + }, + "media_play_pause": { + "name": "Play/Pause", + "description": "Toggles play/pause." + }, + "media_play": { + "name": "Play", + "description": "Starts playing." + }, + "media_pause": { + "name": "Pause", + "description": "Pauses." + }, + "media_stop": { + "name": "Stop", + "description": "Stops playing." + }, + "media_next_track": { + "name": "Next", + "description": "Selects the next track." + }, + "media_previous_track": { + "name": "Previous", + "description": "Selects the previous track." + }, + "media_seek": { + "name": "Seek", + "description": "Allows you to go to a different part of the media that is currently playing.", + "fields": { + "seek_position": { + "name": "Position", + "description": "Target position in the currently playing media. The format is platform dependent." + } + } + }, + "play_media": { + "name": "Play media", + "description": "Starts playing specified media.", + "fields": { + "media_content_id": { + "name": "Content ID", + "description": "The ID of the content to play. Platform dependent." + }, + "media_content_type": { + "name": "Content type", + "description": "The type of the content to play. Such as image, music, tv show, video, episode, channel, or playlist." + }, + "enqueue": { + "name": "Enqueue", + "description": "If the content should be played now or be added to the queue." + }, + "announce": { + "name": "Announce", + "description": "If the media should be played as an announcement." + } + } + }, + "select_source": { + "name": "Select source", + "description": "Sends the media player the command to change input source.", + "fields": { + "source": { + "name": "Source", + "description": "Name of the source to switch to. Platform dependent." + } + } + }, + "select_sound_mode": { + "name": "Select sound mode", + "description": "Selects a specific sound mode.", + "fields": { + "sound_mode": { + "name": "Sound mode", + "description": "Name of the sound mode to switch to." + } + } + }, + "clear_playlist": { + "name": "Clear playlist", + "description": "Clears the playlist." + }, + "shuffle_set": { + "name": "Shuffle", + "description": "Playback mode that selects the media in randomized order.", + "fields": { + "shuffle": { + "name": "Shuffle", + "description": "Whether or not shuffle mode is enabled." + } + } + }, + "repeat_set": { + "name": "Repeat", + "description": "Playback mode that plays the media in a loop.", + "fields": { + "repeat": { + "name": "Repeat mode", + "description": "Repeat mode to set." + } + } + }, + "join": { + "name": "Join", + "description": "Groups media players together for synchronous playback. Only works on supported multiroom audio systems.", + "fields": { + "group_members": { + "name": "Group members", + "description": "The players which will be synced with the playback specified in `target`." + } + } + }, + "unjoin": { + "name": "Unjoin", + "description": "Removes the player from a group. Only works on platforms which support player groups." + } + }, + "selector": { + "enqueue": { + "options": { + "play": "Play", + "next": "Play next", + "add": "Add to queue", + "replace": "Play now and clear queue" + } + }, + "repeat": { + "options": { + "off": "Off", + "all": "Repeat all", + "one": "Repeat one" + } + } } } From 594d240a968d3ad1fed356c7e2706d32fe2ebbba Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 16:37:18 +0200 Subject: [PATCH 094/154] Migrate & fix logger services to support translations (#96393) * Migrate logger services to support translations * Fix tests and schema validation * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/logger/services.yaml | 26 +++++----------- homeassistant/components/logger/strings.json | 30 +++++++++++++++++++ homeassistant/helpers/service.py | 2 +- tests/helpers/test_service.py | 3 ++ 4 files changed, 41 insertions(+), 20 deletions(-) create mode 100644 homeassistant/components/logger/strings.json diff --git a/homeassistant/components/logger/services.yaml b/homeassistant/components/logger/services.yaml index c20d1171bb2528..d7d2a5b32e8fcc 100644 --- a/homeassistant/components/logger/services.yaml +++ b/homeassistant/components/logger/services.yaml @@ -1,26 +1,14 @@ set_default_level: - name: Set default level - description: Set the default log level for integrations. fields: level: - name: Level - description: Default severity level for all integrations. selector: select: options: - - label: "Debug" - value: "debug" - - label: "Info" - value: "info" - - label: "Warning" - value: "warning" - - label: "Error" - value: "error" - - label: "Fatal" - value: "fatal" - - label: "Critical" - value: "critical" - + - "debug" + - "info" + - "warning" + - "error" + - "fatal" + - "critical" + translation_key: level set_level: - name: Set level - description: Set log level for integrations. diff --git a/homeassistant/components/logger/strings.json b/homeassistant/components/logger/strings.json new file mode 100644 index 00000000000000..aedaec420351bc --- /dev/null +++ b/homeassistant/components/logger/strings.json @@ -0,0 +1,30 @@ +{ + "services": { + "set_default_level": { + "name": "Set default level", + "description": "Sets the default log level for integrations.", + "fields": { + "level": { + "name": "Level", + "description": "Default severity level for all integrations." + } + } + }, + "set_level": { + "name": "Set level", + "description": "Sets the log level for one or more integrations." + } + }, + "selector": { + "level": { + "options": { + "debug": "Debug", + "info": "Info", + "warning": "Warning", + "error": "Error", + "fatal": "Fatal", + "critical": "Critical" + } + } + } +} diff --git a/homeassistant/helpers/service.py b/homeassistant/helpers/service.py index 946340ea69cae7..ab0b4ea32e9610 100644 --- a/homeassistant/helpers/service.py +++ b/homeassistant/helpers/service.py @@ -173,7 +173,7 @@ def validate_supported_feature(supported_feature: str) -> Any: extra=vol.ALLOW_EXTRA, ) -_SERVICES_SCHEMA = vol.Schema({cv.slug: _SERVICE_SCHEMA}) +_SERVICES_SCHEMA = vol.Schema({cv.slug: vol.Any(None, _SERVICE_SCHEMA)}) class ServiceParams(TypedDict): diff --git a/tests/helpers/test_service.py b/tests/helpers/test_service.py index a99f303f6c99f7..674d2e1af4c243 100644 --- a/tests/helpers/test_service.py +++ b/tests/helpers/test_service.py @@ -677,6 +677,9 @@ async def test_async_get_all_descriptions_failing_integration( with patch( "homeassistant.helpers.service.async_get_integrations", return_value={"logger": ImportError}, + ), patch( + "homeassistant.helpers.service.translation.async_get_translations", + return_value={}, ): descriptions = await service.async_get_all_descriptions(hass) From dc2406ae09164bf9e207c30037d5c8a77a0d0d07 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 16:37:30 +0200 Subject: [PATCH 095/154] Migrate alarm control panel services to support translations (#96305) * Migrate alarm control panel services to support translations * String references * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- .../alarm_control_panel/services.yaml | 28 -------- .../alarm_control_panel/strings.json | 72 +++++++++++++++++++ 2 files changed, 72 insertions(+), 28 deletions(-) diff --git a/homeassistant/components/alarm_control_panel/services.yaml b/homeassistant/components/alarm_control_panel/services.yaml index c3022b87eb7684..f7a3854b6b3353 100644 --- a/homeassistant/components/alarm_control_panel/services.yaml +++ b/homeassistant/components/alarm_control_panel/services.yaml @@ -1,22 +1,16 @@ # Describes the format for available alarm control panel services alarm_disarm: - name: Disarm - description: Send the alarm the command for disarm. target: entity: domain: alarm_control_panel fields: code: - name: Code - description: An optional code to disarm the alarm control panel with. example: "1234" selector: text: alarm_arm_custom_bypass: - name: Arm with custom bypass - description: Send arm custom bypass command. target: entity: domain: alarm_control_panel @@ -24,15 +18,11 @@ alarm_arm_custom_bypass: - alarm_control_panel.AlarmControlPanelEntityFeature.ARM_CUSTOM_BYPASS fields: code: - name: Code - description: An optional code to arm custom bypass the alarm control panel with. example: "1234" selector: text: alarm_arm_home: - name: Arm home - description: Send the alarm the command for arm home. target: entity: domain: alarm_control_panel @@ -40,15 +30,11 @@ alarm_arm_home: - alarm_control_panel.AlarmControlPanelEntityFeature.ARM_HOME fields: code: - name: Code - description: An optional code to arm home the alarm control panel with. example: "1234" selector: text: alarm_arm_away: - name: Arm away - description: Send the alarm the command for arm away. target: entity: domain: alarm_control_panel @@ -56,15 +42,11 @@ alarm_arm_away: - alarm_control_panel.AlarmControlPanelEntityFeature.ARM_AWAY fields: code: - name: Code - description: An optional code to arm away the alarm control panel with. example: "1234" selector: text: alarm_arm_night: - name: Arm night - description: Send the alarm the command for arm night. target: entity: domain: alarm_control_panel @@ -72,15 +54,11 @@ alarm_arm_night: - alarm_control_panel.AlarmControlPanelEntityFeature.ARM_NIGHT fields: code: - name: Code - description: An optional code to arm night the alarm control panel with. example: "1234" selector: text: alarm_arm_vacation: - name: Arm vacation - description: Send the alarm the command for arm vacation. target: entity: domain: alarm_control_panel @@ -88,15 +66,11 @@ alarm_arm_vacation: - alarm_control_panel.AlarmControlPanelEntityFeature.ARM_VACATION fields: code: - name: Code - description: An optional code to arm vacation the alarm control panel with. example: "1234" selector: text: alarm_trigger: - name: Trigger - description: Send the alarm the command for trigger. target: entity: domain: alarm_control_panel @@ -104,8 +78,6 @@ alarm_trigger: - alarm_control_panel.AlarmControlPanelEntityFeature.TRIGGER fields: code: - name: Code - description: An optional code to trigger the alarm control panel with. example: "1234" selector: text: diff --git a/homeassistant/components/alarm_control_panel/strings.json b/homeassistant/components/alarm_control_panel/strings.json index 6b01cab2beccfe..deaab6d75eedad 100644 --- a/homeassistant/components/alarm_control_panel/strings.json +++ b/homeassistant/components/alarm_control_panel/strings.json @@ -62,5 +62,77 @@ } } } + }, + "services": { + "alarm_disarm": { + "name": "Disarm", + "description": "Disarms the alarm.", + "fields": { + "code": { + "name": "Code", + "description": "Code to disarm the alarm." + } + } + }, + "alarm_arm_custom_bypass": { + "name": "Arm with custom bypass", + "description": "Arms the alarm while allowing to bypass a custom area.", + "fields": { + "code": { + "name": "[%key:component::alarm_control_panel::services::alarm_disarm::fields::code::name%]", + "description": "Code to arm the alarm." + } + } + }, + "alarm_arm_home": { + "name": "Arm home", + "description": "Sets the alarm to: _armed, but someone is home_.", + "fields": { + "code": { + "name": "[%key:component::alarm_control_panel::services::alarm_disarm::fields::code::name%]", + "description": "[%key:component::alarm_control_panel::services::alarm_arm_custom_bypass::fields::code::description%]" + } + } + }, + "alarm_arm_away": { + "name": "Arm away", + "description": "Sets the alarm to: _armed, no one home_.", + "fields": { + "code": { + "name": "[%key:component::alarm_control_panel::services::alarm_disarm::fields::code::name%]", + "description": "[%key:component::alarm_control_panel::services::alarm_arm_custom_bypass::fields::code::description%]" + } + } + }, + "alarm_arm_night": { + "name": "Arm night", + "description": "Sets the alarm to: _armed for the night_.", + "fields": { + "code": { + "name": "[%key:component::alarm_control_panel::services::alarm_disarm::fields::code::name%]", + "description": "[%key:component::alarm_control_panel::services::alarm_arm_custom_bypass::fields::code::description%]" + } + } + }, + "alarm_arm_vacation": { + "name": "Arm vacation", + "description": "Sets the alarm to: _armed for vacation_.", + "fields": { + "code": { + "name": "[%key:component::alarm_control_panel::services::alarm_disarm::fields::code::name%]", + "description": "[%key:component::alarm_control_panel::services::alarm_arm_custom_bypass::fields::code::description%]" + } + } + }, + "alarm_trigger": { + "name": "Trigger", + "description": "Enables an external alarm trigger.", + "fields": { + "code": { + "name": "[%key:component::alarm_control_panel::services::alarm_disarm::fields::code::name%]", + "description": "[%key:component::alarm_control_panel::services::alarm_arm_custom_bypass::fields::code::description%]" + } + } + } } } From d0b7a477687926b2ea64a940c308786be68e82e0 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 16:37:59 +0200 Subject: [PATCH 096/154] Migrate mqtt services to support translations (#96396) * Migrate mqtt services to support translations * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/mqtt/services.yaml | 22 ---------- homeassistant/components/mqtt/strings.json | 46 +++++++++++++++++++++ 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/homeassistant/components/mqtt/services.yaml b/homeassistant/components/mqtt/services.yaml index 07507035c57eff..4960cf9fb82636 100644 --- a/homeassistant/components/mqtt/services.yaml +++ b/homeassistant/components/mqtt/services.yaml @@ -1,32 +1,22 @@ # Describes the format for available MQTT services publish: - name: Publish - description: Publish a message to an MQTT topic. fields: topic: - name: Topic - description: Topic to publish payload. required: true example: /homeassistant/hello selector: text: payload: - name: Payload - description: Payload to publish. example: This is great selector: text: payload_template: - name: Payload Template - description: Template to render as payload value. Ignored if payload given. advanced: true example: "{{ states('sensor.temperature') }}" selector: object: qos: - name: QoS - description: Quality of Service to use. advanced: true default: 0 selector: @@ -36,27 +26,17 @@ publish: - "1" - "2" retain: - name: Retain - description: If message should have the retain flag set. default: false selector: boolean: dump: - name: Dump - description: - Dump messages on a topic selector to the 'mqtt_dump.txt' file in your - configuration folder. fields: topic: - name: Topic - description: topic to listen to example: "OpenZWave/#" selector: text: duration: - name: Duration - description: how long we should listen for messages in seconds default: 5 selector: number: @@ -65,5 +45,3 @@ dump: unit_of_measurement: "seconds" reload: - name: Reload - description: Reload all MQTT entities from YAML. diff --git a/homeassistant/components/mqtt/strings.json b/homeassistant/components/mqtt/strings.json index 3423b2cd470102..61d2b40314b135 100644 --- a/homeassistant/components/mqtt/strings.json +++ b/homeassistant/components/mqtt/strings.json @@ -145,5 +145,51 @@ "custom": "Custom" } } + }, + "services": { + "publish": { + "name": "Publish", + "description": "Publishes a message to an MQTT topic.", + "fields": { + "topic": { + "name": "Topic", + "description": "Topic to publish to." + }, + "payload": { + "name": "Payload", + "description": "The payload to publish." + }, + "payload_template": { + "name": "Payload template", + "description": "Template to render as a payload value. If a payload is provided, the template is ignored." + }, + "qos": { + "name": "QoS", + "description": "Quality of Service to use. O. At most once. 1: At least once. 2: Exactly once." + }, + "retain": { + "name": "Retain", + "description": "If the message should have the retain flag set. If set, the broker stores the most recent message on a topic." + } + } + }, + "dump": { + "name": "Export", + "description": "Writes all messages on a specific topic into the `mqtt_dump.txt` file in your configuration folder.", + "fields": { + "topic": { + "name": "Topic", + "description": "Topic to listen to." + }, + "duration": { + "name": "Duration", + "description": "How long we should listen for messages in seconds." + } + } + }, + "reload": { + "name": "Reload", + "description": "Reloads MQTT entities from the YAML-configuration." + } } } From 6c40004061039ee5bc8a9e88c78aede0bd9e7988 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 16:38:47 +0200 Subject: [PATCH 097/154] Migrate integration services (I-K) to support translations (#96373) * Migrate integration services (I-K) to support translations * Apply suggestions from code review Co-authored-by: Joost Lekkerkerker * Update homeassistant/components/kodi/strings.json Co-authored-by: Joost Lekkerkerker --------- Co-authored-by: Joost Lekkerkerker --- homeassistant/components/icloud/services.yaml | 30 ----- homeassistant/components/icloud/strings.json | 70 ++++++++++ homeassistant/components/ifttt/services.yaml | 15 --- homeassistant/components/ifttt/strings.json | 38 ++++++ homeassistant/components/ihc/services.yaml | 38 ------ homeassistant/components/ihc/strings.json | 72 +++++++++++ .../components/insteon/services.yaml | 46 ------- homeassistant/components/insteon/strings.json | 114 +++++++++++++++++ homeassistant/components/iperf3/services.yaml | 4 - homeassistant/components/iperf3/strings.json | 14 ++ homeassistant/components/isy994/services.yaml | 63 --------- homeassistant/components/isy994/strings.json | 120 +++++++++++++++++- homeassistant/components/izone/services.yaml | 8 -- homeassistant/components/izone/strings.json | 22 ++++ homeassistant/components/keba/services.yaml | 44 ------- homeassistant/components/keba/strings.json | 62 +++++++++ homeassistant/components/kef/services.yaml | 40 ------ homeassistant/components/kef/strings.json | 98 ++++++++++++++ .../components/keyboard/services.yaml | 29 ----- .../components/keyboard/strings.json | 28 ++++ .../components/keymitt_ble/services.yaml | 10 -- .../components/keymitt_ble/strings.json | 24 ++++ homeassistant/components/knx/services.yaml | 38 ------ homeassistant/components/knx/strings.json | 86 +++++++++++++ homeassistant/components/kodi/services.yaml | 14 -- homeassistant/components/kodi/strings.json | 34 +++++ 26 files changed, 781 insertions(+), 380 deletions(-) create mode 100644 homeassistant/components/ihc/strings.json create mode 100644 homeassistant/components/iperf3/strings.json create mode 100644 homeassistant/components/keba/strings.json create mode 100644 homeassistant/components/kef/strings.json create mode 100644 homeassistant/components/keyboard/strings.json diff --git a/homeassistant/components/icloud/services.yaml b/homeassistant/components/icloud/services.yaml index ddeae448f8a51e..5ffbc2a49ae715 100644 --- a/homeassistant/components/icloud/services.yaml +++ b/homeassistant/components/icloud/services.yaml @@ -1,93 +1,63 @@ update: - name: Update - description: Update iCloud devices. fields: account: - name: Account - description: Your iCloud account username (email) or account name. required: true example: "steve@apple.com" selector: text: play_sound: - name: Play sound - description: Play sound on an Apple device. fields: account: - name: Account - description: Your iCloud account username (email) or account name. required: true example: "steve@apple.com" selector: text: device_name: - name: Device Name - description: The name of the Apple device to play a sound. required: true example: "stevesiphone" selector: text: display_message: - name: Display message - description: Display a message on an Apple device. fields: account: - name: Account - description: Your iCloud account username (email) or account name. required: true example: "steve@apple.com" selector: text: device_name: - name: Device Name - description: The name of the Apple device to display the message. required: true example: "stevesiphone" selector: text: message: - name: Message - description: The content of your message. required: true example: "Hey Steve !" selector: text: sound: - name: Sound - description: To make a sound when displaying the message. selector: boolean: lost_device: - name: Lost device - description: Make an Apple device in lost state. fields: account: - name: Account - description: Your iCloud account username (email) or account name. required: true example: "steve@apple.com" selector: text: device_name: - name: Device Name - description: The name of the Apple device to set lost. required: true example: "stevesiphone" selector: text: number: - name: Number - description: The phone number to call in lost mode (must contain country code). required: true example: "+33450020100" selector: text: message: - name: Message - description: The message to display in lost mode. required: true example: "Call me" selector: diff --git a/homeassistant/components/icloud/strings.json b/homeassistant/components/icloud/strings.json index 385dc74a0ab83e..9bc7750790f308 100644 --- a/homeassistant/components/icloud/strings.json +++ b/homeassistant/components/icloud/strings.json @@ -42,5 +42,75 @@ "no_device": "None of your devices have \"Find my iPhone\" activated", "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" } + }, + "services": { + "update": { + "name": "Update", + "description": "Updates iCloud devices.", + "fields": { + "account": { + "name": "Account", + "description": "Your iCloud account username (email) or account name." + } + } + }, + "play_sound": { + "name": "Play sound", + "description": "Plays sound on an Apple device.", + "fields": { + "account": { + "name": "Account", + "description": "Your iCloud account username (email) or account name." + }, + "device_name": { + "name": "Device name", + "description": "The name of the Apple device to play a sound." + } + } + }, + "display_message": { + "name": "Display message", + "description": "Displays a message on an Apple device.", + "fields": { + "account": { + "name": "Account", + "description": "Your iCloud account username (email) or account name." + }, + "device_name": { + "name": "Device name", + "description": "The name of the Apple device to display the message." + }, + "message": { + "name": "Message", + "description": "The content of your message." + }, + "sound": { + "name": "Sound", + "description": "To make a sound when displaying the message." + } + } + }, + "lost_device": { + "name": "Lost device", + "description": "Makes an Apple device in lost state.", + "fields": { + "account": { + "name": "Account", + "description": "Your iCloud account username (email) or account name." + }, + "device_name": { + "name": "Device name", + "description": "The name of the Apple device to set lost." + }, + "number": { + "name": "Number", + "description": "The phone number to call in lost mode (must contain country code)." + }, + "message": { + "name": "Message", + "description": "The message to display in lost mode." + } + } + } } } diff --git a/homeassistant/components/ifttt/services.yaml b/homeassistant/components/ifttt/services.yaml index 9c02284d4f883b..550aecad56be58 100644 --- a/homeassistant/components/ifttt/services.yaml +++ b/homeassistant/components/ifttt/services.yaml @@ -1,49 +1,34 @@ # Describes the format for available ifttt services push_alarm_state: - name: Push alarm state - description: Update the alarm state to the specified value. fields: entity_id: - description: Name of the alarm control panel which state has to be updated. required: true selector: entity: domain: alarm_control_panel state: - name: State - description: The state to which the alarm control panel has to be set. required: true example: "armed_night" selector: text: trigger: - name: Trigger - description: Triggers the configured IFTTT Webhook. fields: event: - name: Event - description: The name of the event to send. required: true example: "MY_HA_EVENT" selector: text: value1: - name: Value 1 - description: Generic field to send data via the event. example: "Hello World" selector: text: value2: - name: Value 2 - description: Generic field to send data via the event. example: "some additional data" selector: text: value3: - name: Value 3 - description: Generic field to send data via the event. example: "even more data" selector: text: diff --git a/homeassistant/components/ifttt/strings.json b/homeassistant/components/ifttt/strings.json index 179d62b463c5cc..e52a0882eb1b0d 100644 --- a/homeassistant/components/ifttt/strings.json +++ b/homeassistant/components/ifttt/strings.json @@ -14,5 +14,43 @@ "create_entry": { "default": "To send events to Home Assistant, you will need to use the \"Make a web request\" action from the [IFTTT Webhook applet]({applet_url}).\n\nFill in the following info:\n\n- URL: `{webhook_url}`\n- Method: POST\n- Content Type: application/json\n\nSee [the documentation]({docs_url}) on how to configure automations to handle incoming data." } + }, + "services": { + "push_alarm_state": { + "name": "Push alarm state", + "description": "Updates the alarm state to the specified value.", + "fields": { + "entity_id": { + "name": "Entity ID", + "description": "Name of the alarm control panel which state has to be updated." + }, + "state": { + "name": "State", + "description": "The state to which the alarm control panel has to be set." + } + } + }, + "trigger": { + "name": "Trigger", + "description": "Triggers the configured IFTTT Webhook.", + "fields": { + "event": { + "name": "Event", + "description": "The name of the event to send." + }, + "value1": { + "name": "Value 1", + "description": "Generic field to send data via the event." + }, + "value2": { + "name": "Value 2", + "description": "Generic field to send data via the event." + }, + "value3": { + "name": "Value 3", + "description": "Generic field to send data via the event." + } + } + } } } diff --git a/homeassistant/components/ihc/services.yaml b/homeassistant/components/ihc/services.yaml index 33f6c8ca31d6db..1e1727abea87dd 100644 --- a/homeassistant/components/ihc/services.yaml +++ b/homeassistant/components/ihc/services.yaml @@ -1,22 +1,14 @@ # Describes the format for available IHC services set_runtime_value_bool: - name: Set runtime value boolean - description: Set a boolean runtime value on the IHC controller. fields: controller_id: - name: Controller ID - description: | - If you have multiple controller, this is the index of you controller - starting with 0. default: 0 selector: number: min: 0 max: 100 ihc_id: - name: IHC ID - description: The integer IHC resource ID. required: true selector: number: @@ -24,29 +16,19 @@ set_runtime_value_bool: max: 1000000 mode: box value: - name: Value - description: The boolean value to set. required: true selector: boolean: set_runtime_value_int: - name: Set runtime value integer - description: Set an integer runtime value on the IHC controller. fields: controller_id: - name: Controller ID - description: | - If you have multiple controller, this is the index of you controller - starting with 0. default: 0 selector: number: min: 0 max: 100 ihc_id: - name: IHC ID - description: The integer IHC resource ID. required: true selector: number: @@ -54,8 +36,6 @@ set_runtime_value_int: max: 1000000 mode: box value: - name: Value - description: The integer value to set. required: true selector: number: @@ -64,22 +44,14 @@ set_runtime_value_int: mode: box set_runtime_value_float: - name: Set runtime value float - description: Set a float runtime value on the IHC controller. fields: controller_id: - name: Controller ID - description: | - If you have multiple controller, this is the index of you controller - starting with 0. default: 0 selector: number: min: 0 max: 100 ihc_id: - name: IHC ID - description: The integer IHC resource ID. required: true selector: number: @@ -87,8 +59,6 @@ set_runtime_value_float: max: 1000000 mode: box value: - name: Value - description: The float value to set. required: true selector: number: @@ -98,22 +68,14 @@ set_runtime_value_float: mode: box pulse: - name: Pulse - description: Pulses an input on the IHC controller. fields: controller_id: - name: Controller ID - description: | - If you have multiple controller, this is the index of you controller - starting with 0. default: 0 selector: number: min: 0 max: 100 ihc_id: - name: IHC ID - description: The integer IHC resource ID. required: true selector: number: diff --git a/homeassistant/components/ihc/strings.json b/homeassistant/components/ihc/strings.json new file mode 100644 index 00000000000000..3ee45a4f4649ec --- /dev/null +++ b/homeassistant/components/ihc/strings.json @@ -0,0 +1,72 @@ +{ + "services": { + "set_runtime_value_bool": { + "name": "Set runtime value boolean", + "description": "Sets a boolean runtime value on the IHC controller.", + "fields": { + "controller_id": { + "name": "Controller ID", + "description": "If you have multiple controller, this is the index of you controller\nstarting with 0.\n." + }, + "ihc_id": { + "name": "IHC ID", + "description": "The integer IHC resource ID." + }, + "value": { + "name": "Value", + "description": "The boolean value to set." + } + } + }, + "set_runtime_value_int": { + "name": "Set runtime value integer", + "description": "Sets an integer runtime value on the IHC controller.", + "fields": { + "controller_id": { + "name": "Controller ID", + "description": "If you have multiple controller, this is the index of you controller\nstarting with 0.\n." + }, + "ihc_id": { + "name": "IHC ID", + "description": "The integer IHC resource ID." + }, + "value": { + "name": "Value", + "description": "The integer value to set." + } + } + }, + "set_runtime_value_float": { + "name": "Set runtime value float", + "description": "Sets a float runtime value on the IHC controller.", + "fields": { + "controller_id": { + "name": "Controller ID", + "description": "If you have multiple controller, this is the index of you controller\nstarting with 0.\n." + }, + "ihc_id": { + "name": "IHC ID", + "description": "The integer IHC resource ID." + }, + "value": { + "name": "Value", + "description": "The float value to set." + } + } + }, + "pulse": { + "name": "Pulse", + "description": "Pulses an input on the IHC controller.", + "fields": { + "controller_id": { + "name": "Controller ID", + "description": "If you have multiple controller, this is the index of you controller\nstarting with 0.\n." + }, + "ihc_id": { + "name": "IHC ID", + "description": "The integer IHC resource ID." + } + } + } + } +} diff --git a/homeassistant/components/insteon/services.yaml b/homeassistant/components/insteon/services.yaml index 164c917c793c64..a58dfb4b8ce0a4 100644 --- a/homeassistant/components/insteon/services.yaml +++ b/homeassistant/components/insteon/services.yaml @@ -1,18 +1,12 @@ add_all_link: - name: Add all link - description: Tells the Insteom Modem (IM) start All-Linking mode. Once the IM is in All-Linking mode, press the link button on the device to complete All-Linking. fields: group: - name: Group - description: All-Link group number. required: true selector: number: min: 0 max: 255 mode: - name: Mode - description: Linking mode controller - IM is controller responder - IM is responder required: true selector: select: @@ -20,55 +14,35 @@ add_all_link: - "controller" - "responder" delete_all_link: - name: Delete all link - description: Tells the Insteon Modem (IM) to remove an All-Link record from the All-Link Database of the IM and a device. Once the IM is set to delete the link, press the link button on the corresponding device to complete the process. fields: group: - name: Group - description: All-Link group number. required: true selector: number: min: 0 max: 255 load_all_link_database: - name: Load all link database - description: Load the All-Link Database for a device. WARNING - Loading a device All-LInk database is very time consuming and inconsistent. This may take a LONG time and may need to be repeated to obtain all records. fields: entity_id: - name: Entity - description: Name of the device to load. Use "all" to load the database of all devices. required: true example: "light.1a2b3c" selector: text: reload: - name: Reload - description: Reload all records. If true the current records are cleared from memory (does not effect the device) and the records are reloaded. If false the existing records are left in place and only missing records are added. Default is false. default: false selector: boolean: print_all_link_database: - name: Print all link database - description: Print the All-Link Database for a device. Requires that the All-Link Database is loaded into memory. fields: entity_id: - name: Entity - description: Name of the device to print required: true selector: entity: integration: insteon print_im_all_link_database: - name: Print IM all link database - description: Print the All-Link Database for the INSTEON Modem (IM). x10_all_units_off: - name: X10 all units off - description: Send X10 All Units Off command fields: housecode: - name: Housecode - description: X10 house code required: true selector: select: @@ -90,12 +64,8 @@ x10_all_units_off: - "o" - "p" x10_all_lights_on: - name: X10 all lights on - description: Send X10 All Lights On command fields: housecode: - name: Housecode - description: X10 house code required: true selector: select: @@ -117,12 +87,8 @@ x10_all_lights_on: - "o" - "p" x10_all_lights_off: - name: X10 all lights off - description: Send X10 All Lights Off command fields: housecode: - name: Housecode - description: X10 house code required: true selector: select: @@ -144,36 +110,24 @@ x10_all_lights_off: - "o" - "p" scene_on: - name: Scene on - description: Trigger an INSTEON scene to turn ON. fields: group: - name: Group - description: INSTEON group or scene number required: true selector: number: min: 0 max: 255 scene_off: - name: Scene off - description: Trigger an INSTEON scene to turn OFF. fields: group: - name: Group - description: INSTEON group or scene number required: true selector: number: min: 0 max: 255 add_default_links: - name: Add default links - description: Add the default links between the device and the Insteon Modem (IM) fields: entity_id: - name: Entity - description: Name of the device to load. Use "all" to load the database of all devices. required: true example: "light.1a2b3c" selector: diff --git a/homeassistant/components/insteon/strings.json b/homeassistant/components/insteon/strings.json index a93ba4a7476aa9..3f3e3df78c7bde 100644 --- a/homeassistant/components/insteon/strings.json +++ b/homeassistant/components/insteon/strings.json @@ -109,5 +109,119 @@ "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "input_error": "Invalid entries, please check your values." } + }, + "services": { + "add_all_link": { + "name": "Add all link", + "description": "Tells the Insteom Modem (IM) start All-Linking mode. Once the IM is in All-Linking mode, press the link button on the device to complete All-Linking.", + "fields": { + "group": { + "name": "Group", + "description": "All-Link group number." + }, + "mode": { + "name": "Mode", + "description": "Linking mode controller - IM is controller responder - IM is responder." + } + } + }, + "delete_all_link": { + "name": "Delete all link", + "description": "Tells the Insteon Modem (IM) to remove an All-Link record from the All-Link Database of the IM and a device. Once the IM is set to delete the link, press the link button on the corresponding device to complete the process.", + "fields": { + "group": { + "name": "Group", + "description": "All-Link group number." + } + } + }, + "load_all_link_database": { + "name": "Load all link database", + "description": "Load the All-Link Database for a device. WARNING - Loading a device All-LInk database is very time consuming and inconsistent. This may take a LONG time and may need to be repeated to obtain all records.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name of the device to load. Use \"all\" to load the database of all devices." + }, + "reload": { + "name": "Reload", + "description": "Reloads all records. If true the current records are cleared from memory (does not effect the device) and the records are reloaded. If false the existing records are left in place and only missing records are added. Default is false." + } + } + }, + "print_all_link_database": { + "name": "Print all link database", + "description": "Prints the All-Link Database for a device. Requires that the All-Link Database is loaded into memory.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name of the device to print." + } + } + }, + "print_im_all_link_database": { + "name": "Print IM all link database", + "description": "Prints the All-Link Database for the INSTEON Modem (IM)." + }, + "x10_all_units_off": { + "name": "X10 all units off", + "description": "Tells the Insteom Modem (IM) start All-Linking mode. Once the IM is in All-Linking mode, press the link button on the device to complete All-Linking.", + "fields": { + "housecode": { + "name": "Housecode", + "description": "X10 house code." + } + } + }, + "x10_all_lights_on": { + "name": "X10 all lights on", + "description": "Sends X10 All Lights On command.", + "fields": { + "housecode": { + "name": "Housecode", + "description": "X10 house code." + } + } + }, + "x10_all_lights_off": { + "name": "X10 all lights off", + "description": "Sends X10 All Lights Off command.", + "fields": { + "housecode": { + "name": "Housecode", + "description": "X10 house code." + } + } + }, + "scene_on": { + "name": "Scene on", + "description": "Triggers an INSTEON scene to turn ON.", + "fields": { + "group": { + "name": "Group", + "description": "INSTEON group or scene number." + } + } + }, + "scene_off": { + "name": "Scene off", + "description": "Triggers an INSTEON scene to turn OFF.", + "fields": { + "group": { + "name": "Group", + "description": "INSTEON group or scene number." + } + } + }, + "add_default_links": { + "name": "Add default links", + "description": "Adds the default links between the device and the Insteon Modem (IM).", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name of the device to load. Use \"all\" to load the database of all devices." + } + } + } } } diff --git a/homeassistant/components/iperf3/services.yaml b/homeassistant/components/iperf3/services.yaml index ba0fdb89712897..b0cc4f11639d89 100644 --- a/homeassistant/components/iperf3/services.yaml +++ b/homeassistant/components/iperf3/services.yaml @@ -1,10 +1,6 @@ speedtest: - name: Speedtest - description: Immediately execute a speed test with iperf3 fields: host: - name: Host - description: The host name of the iperf3 server (already configured) to run a test with. example: "iperf.he.net" default: None selector: diff --git a/homeassistant/components/iperf3/strings.json b/homeassistant/components/iperf3/strings.json new file mode 100644 index 00000000000000..be8535daec67cb --- /dev/null +++ b/homeassistant/components/iperf3/strings.json @@ -0,0 +1,14 @@ +{ + "services": { + "speedtest": { + "name": "Speedtest", + "description": "Immediately executes a speed test with iperf3.", + "fields": { + "host": { + "name": "Host", + "description": "The host name of the iperf3 server (already configured) to run a test with." + } + } + } + } +} diff --git a/homeassistant/components/isy994/services.yaml b/homeassistant/components/isy994/services.yaml index b84fcdd73ef342..7ce44f9edae3f6 100644 --- a/homeassistant/components/isy994/services.yaml +++ b/homeassistant/components/isy994/services.yaml @@ -4,52 +4,36 @@ # flooding the ISY with requests. To control multiple devices with a service call # the recommendation is to add a scene in the ISY and control that scene. send_raw_node_command: - name: Send raw node command - description: Send a "raw" ISY REST Device Command to a Node using its Home Assistant Entity ID. target: entity: integration: isy994 fields: command: - name: Command - description: The ISY REST Command to be sent to the device required: true example: "DON" selector: text: value: - name: Value - description: The integer value to be sent with the command. selector: number: min: 0 max: 255 parameters: - name: Parameters - description: A dict of parameters to be sent in the query string (e.g. for controlling colored bulbs). example: { GV2: 0, GV3: 0, GV4: 255 } default: {} selector: object: unit_of_measurement: - name: Unit of measurement - description: The ISY Unit of Measurement (UOM) to send with the command, if required. selector: number: min: 0 max: 120 send_node_command: - name: Send node command - description: >- - Send a command to an ISY Device using its Home Assistant entity ID. Valid commands are: beep, brighten, dim, disable, - enable, fade_down, fade_stop, fade_up, fast_off, fast_on, and query. target: entity: integration: isy994 fields: command: - name: Command - description: The command to be sent to the device. required: true selector: select: @@ -66,34 +50,22 @@ send_node_command: - "fast_on" - "query" get_zwave_parameter: - name: Get Z-Wave Parameter - description: >- - Request a Z-Wave Device parameter via the ISY. The parameter value will be returned as a entity extra state attribute with the name "ZW_#" - where "#" is the parameter number. target: entity: integration: isy994 fields: parameter: - name: Parameter - description: The parameter number to retrieve from the device. example: 8 selector: number: min: 1 max: 255 set_zwave_parameter: - name: Set Z-Wave Parameter - description: >- - Update a Z-Wave Device parameter via the ISY. The parameter value will also be returned as a entity extra state attribute with the name "ZW_#" - where "#" is the parameter number. target: entity: integration: isy994 fields: parameter: - name: Parameter - description: The parameter number to set on the end device. required: true example: 8 selector: @@ -101,15 +73,11 @@ set_zwave_parameter: min: 1 max: 255 value: - name: Value - description: The value to set for the parameter. May be an integer or byte string (e.g. "0xFFFF"). required: true example: 33491663 selector: text: size: - name: Size - description: The size of the parameter, either 1, 2, or 4 bytes. required: true example: 4 selector: @@ -119,17 +87,12 @@ set_zwave_parameter: - "2" - "4" set_zwave_lock_user_code: - name: Set Z-Wave Lock User Code - description: >- - Set a Z-Wave Lock User Code via the ISY. target: entity: integration: isy994 domain: lock fields: user_num: - name: User Number - description: The user slot number on the lock required: true example: 8 selector: @@ -137,8 +100,6 @@ set_zwave_lock_user_code: min: 1 max: 255 code: - name: Code - description: The code to set for the user. required: true example: 33491663 selector: @@ -147,17 +108,12 @@ set_zwave_lock_user_code: max: 99999999 mode: box delete_zwave_lock_user_code: - name: Delete Z-Wave Lock User Code - description: >- - Delete a Z-Wave Lock User Code via the ISY. target: entity: integration: isy994 domain: lock fields: user_num: - name: User Number - description: The user slot number on the lock required: true example: 8 selector: @@ -165,43 +121,26 @@ delete_zwave_lock_user_code: min: 1 max: 255 rename_node: - name: Rename Node on ISY - description: >- - Rename a node or group (scene) on the ISY. Note: this will not automatically change the Home Assistant Entity Name or Entity ID to match. - The entity name and ID will only be updated after calling `isy994.reload` or restarting Home Assistant, and ONLY IF you have not already customized the - name within Home Assistant. target: entity: integration: isy994 fields: name: - name: New Name - description: The new name to use within the ISY. required: true example: "Front Door Light" selector: text: send_program_command: - name: Send program command - description: >- - Send a command to control an ISY program or folder. Valid commands are run, run_then, run_else, stop, enable, disable, - enable_run_at_startup, and disable_run_at_startup. fields: address: - name: Address - description: The address of the program to control (use either address or name). example: "04B1" selector: text: name: - name: Name - description: The name of the program to control (use either address or name). example: "My Program" selector: text: command: - name: Command - description: The ISY Program Command to be sent. required: true selector: select: @@ -215,8 +154,6 @@ send_program_command: - "run_then" - "stop" isy: - name: ISY - description: If you have more than one ISY connected, provide the name of the ISY to query (as shown on the Device Registry or as the top-first node in the ISY Admin Console). If you have the same program name or address on multiple ISYs, omitting this will run the command on them all. example: "ISY" selector: text: diff --git a/homeassistant/components/isy994/strings.json b/homeassistant/components/isy994/strings.json index 821f8889978688..542df60f13fd60 100644 --- a/homeassistant/components/isy994/strings.json +++ b/homeassistant/components/isy994/strings.json @@ -36,7 +36,7 @@ "step": { "init": { "title": "ISY Options", - "description": "Set the options for the ISY Integration: \n • Node Sensor String: Any device or folder that contains 'Node Sensor String' in the name will be treated as a sensor or binary sensor. \n • Ignore String: Any device with 'Ignore String' in the name will be ignored. \n • Variable Sensor String: Any variable that contains 'Variable Sensor String' will be added as a sensor. \n • Restore Light Brightness: If enabled, the previous brightness will be restored when turning on a light instead of the device's built-in On-Level.", + "description": "Set the options for the ISY Integration: \n \u2022 Node Sensor String: Any device or folder that contains 'Node Sensor String' in the name will be treated as a sensor or binary sensor. \n \u2022 Ignore String: Any device with 'Ignore String' in the name will be ignored. \n \u2022 Variable Sensor String: Any variable that contains 'Variable Sensor String' will be added as a sensor. \n \u2022 Restore Light Brightness: If enabled, the previous brightness will be restored when turning on a light instead of the device's built-in On-Level.", "data": { "sensor_string": "Node Sensor String", "ignore_string": "Ignore String", @@ -53,5 +53,123 @@ "last_heartbeat": "Last Heartbeat Time", "websocket_status": "Event Socket Status" } + }, + "services": { + "send_raw_node_command": { + "name": "Send raw node command", + "description": "Set the options for the ISY Integration: \n \u2022 Node Sensor String: Any device or folder that contains 'Node Sensor String' in the name will be treated as a sensor or binary sensor. \n \u2022 Ignore String: Any device with 'Ignore String' in the name will be ignored. \n \u2022 Variable Sensor String: Any variable that contains 'Variable Sensor String' will be added as a sensor. \n \u2022 Restore Light Brightness: If enabled, the previous brightness will be restored when turning on a light instead of the device's built-in On-Level.", + "fields": { + "command": { + "name": "Command", + "description": "The ISY REST Command to be sent to the device." + }, + "value": { + "name": "Value", + "description": "The integer value to be sent with the command." + }, + "parameters": { + "name": "Parameters", + "description": "A dict of parameters to be sent in the query string (e.g. for controlling colored bulbs)." + }, + "unit_of_measurement": { + "name": "Unit of measurement", + "description": "The ISY Unit of Measurement (UOM) to send with the command, if required." + } + } + }, + "send_node_command": { + "name": "Send node command", + "description": "Sends a command to an ISY Device using its Home Assistant entity ID. Valid commands are: beep, brighten, dim, disable, enable, fade_down, fade_stop, fade_up, fast_off, fast_on, and query.", + "fields": { + "command": { + "name": "Command", + "description": "The command to be sent to the device." + } + } + }, + "get_zwave_parameter": { + "name": "Get Z-Wave Parameter", + "description": "Requests a Z-Wave Device parameter via the ISY. The parameter value will be returned as a entity extra state attribute with the name \"ZW_#\" where \"#\" is the parameter number.", + "fields": { + "parameter": { + "name": "Parameter", + "description": "The parameter number to retrieve from the device." + } + } + }, + "set_zwave_parameter": { + "name": "Set Z-Wave Parameter", + "description": "Updates a Z-Wave Device parameter via the ISY. The parameter value will also be returned as a entity extra state attribute with the name \"ZW_#\" where \"#\" is the parameter number.", + "fields": { + "parameter": { + "name": "Parameter", + "description": "The parameter number to set on the end device." + }, + "value": { + "name": "Value", + "description": "The value to set for the parameter. May be an integer or byte string (e.g. \"0xFFFF\")." + }, + "size": { + "name": "Size", + "description": "The size of the parameter, either 1, 2, or 4 bytes." + } + } + }, + "set_zwave_lock_user_code": { + "name": "Set Z-Wave Lock User Code", + "description": "Sets a Z-Wave Lock User Code via the ISY.", + "fields": { + "user_num": { + "name": "User Number", + "description": "The user slot number on the lock." + }, + "code": { + "name": "Code", + "description": "The code to set for the user." + } + } + }, + "delete_zwave_lock_user_code": { + "name": "Delete Z-Wave Lock User Code", + "description": "Delete a Z-Wave Lock User Code via the ISY.", + "fields": { + "user_num": { + "name": "User Number", + "description": "The user slot number on the lock." + } + } + }, + "rename_node": { + "name": "Rename Node on ISY", + "description": "Renames a node or group (scene) on the ISY. Note: this will not automatically change the Home Assistant Entity Name or Entity ID to match. The entity name and ID will only be updated after calling `isy994.reload` or restarting Home Assistant, and ONLY IF you have not already customized the name within Home Assistant.", + "fields": { + "name": { + "name": "New Name", + "description": "The new name to use within the ISY." + } + } + }, + "send_program_command": { + "name": "Send program command", + "description": "Sends a command to control an ISY program or folder. Valid commands are run, run_then, run_else, stop, enable, disable, enable_run_at_startup, and disable_run_at_startup.", + "fields": { + "address": { + "name": "Address", + "description": "The address of the program to control (use either address or name)." + }, + "name": { + "name": "Name", + "description": "The name of the program to control (use either address or name)." + }, + "command": { + "name": "Command", + "description": "The ISY Program Command to be sent." + }, + "isy": { + "name": "ISY", + "description": "If you have more than one ISY connected, provide the name of the ISY to query (as shown on the Device Registry or as the top-first node in the ISY Admin Console). If you have the same program name or address on multiple ISYs, omitting this will run the command on them all." + } + } + } } } diff --git a/homeassistant/components/izone/services.yaml b/homeassistant/components/izone/services.yaml index 5cecbb68a9f903..f1a8fe5c8e5342 100644 --- a/homeassistant/components/izone/services.yaml +++ b/homeassistant/components/izone/services.yaml @@ -1,14 +1,10 @@ airflow_min: - name: Set minimum airflow - description: Set the airflow minimum percent for a zone target: entity: integration: izone domain: climate fields: airflow: - name: Percent - description: Airflow percent. required: true selector: number: @@ -17,16 +13,12 @@ airflow_min: step: 5 unit_of_measurement: "%" airflow_max: - name: Set maximum airflow - description: Set the airflow maximum percent for a zone target: entity: integration: izone domain: climate fields: airflow: - name: Percent - description: Airflow percent. required: true selector: number: diff --git a/homeassistant/components/izone/strings.json b/homeassistant/components/izone/strings.json index 7d1e8f1d4768ab..3906dcb89fe4fb 100644 --- a/homeassistant/components/izone/strings.json +++ b/homeassistant/components/izone/strings.json @@ -9,5 +9,27 @@ "single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]", "no_devices_found": "[%key:common::config_flow::abort::no_devices_found%]" } + }, + "services": { + "airflow_min": { + "name": "Set minimum airflow", + "description": "Sets the airflow minimum percent for a zone.", + "fields": { + "airflow": { + "name": "Percent", + "description": "Airflow percent." + } + } + }, + "airflow_max": { + "name": "Set maximum airflow", + "description": "Sets the airflow maximum percent for a zone.", + "fields": { + "airflow": { + "name": "Percent", + "description": "Airflow percent." + } + } + } } } diff --git a/homeassistant/components/keba/services.yaml b/homeassistant/components/keba/services.yaml index 8e5e8cd91f88cd..daa1749a34cafa 100644 --- a/homeassistant/components/keba/services.yaml +++ b/homeassistant/components/keba/services.yaml @@ -1,28 +1,11 @@ # Describes the format for available services for KEBA charging staitons request_data: - name: Request data - description: > - Request new data from the charging station. - authorize: - name: Authorize - description: > - Authorizes a charging process with the predefined RFID tag of the configuration file. - deauthorize: - name: Deauthorize - description: > - Deauthorizes the running charging process with the predefined RFID tag of the configuration file. - set_energy: - name: Set energy - description: Sets the energy target after which the charging process stops. fields: energy: - name: Energy - description: > - The energy target to stop charging. Setting 0 disables the limit. selector: number: min: 0 @@ -31,15 +14,8 @@ set_energy: unit_of_measurement: "kWh" set_current: - name: Set current - description: Sets the maximum current for charging processes. fields: current: - name: Current - description: > - The maximum current used for the charging process. - The value is depending on the DIP-switch settings and the used cable of the - charging station. default: 6 selector: number: @@ -49,24 +25,10 @@ set_current: unit_of_measurement: "A" enable: - name: Enable - description: > - Starts a charging process if charging station is authorized. - disable: - name: Disable - description: > - Stops the charging process if charging station is authorized. - set_failsafe: - name: Set failsafe - description: > - Set the failsafe mode of the charging station. If all parameters are 0, the failsafe mode will be disabled. fields: failsafe_timeout: - name: Failsafe timeout - description: > - Timeout after which the failsafe mode is triggered, if set_current was not executed during this time. default: 30 selector: number: @@ -74,9 +36,6 @@ set_failsafe: max: 3600 unit_of_measurement: seconds failsafe_fallback: - name: Failsafe fallback - description: > - Fallback current to be set after timeout. default: 6 selector: number: @@ -85,9 +44,6 @@ set_failsafe: step: 0.1 unit_of_measurement: "A" failsafe_persist: - name: Failsafe persist - description: > - If failsafe_persist is 0, the failsafe option is only until charging station reboot. If failsafe_persist is 1, the failsafe option will survive a reboot. default: 0 selector: number: diff --git a/homeassistant/components/keba/strings.json b/homeassistant/components/keba/strings.json new file mode 100644 index 00000000000000..140ab6ea9490ce --- /dev/null +++ b/homeassistant/components/keba/strings.json @@ -0,0 +1,62 @@ +{ + "services": { + "request_data": { + "name": "Request data", + "description": "Requesta new data from the charging station." + }, + "authorize": { + "name": "Authorize", + "description": "Authorizes a charging process with the predefined RFID tag of the configuration file." + }, + "deauthorize": { + "name": "Deauthorize", + "description": "Deauthorizes the running charging process with the predefined RFID tag of the configuration file." + }, + "set_energy": { + "name": "Set energy", + "description": "Sets the energy target after which the charging process stops.", + "fields": { + "energy": { + "name": "Energy", + "description": "The energy target to stop charging. Setting 0 disables the limit." + } + } + }, + "set_current": { + "name": "Set current", + "description": "Sets the maximum current for charging processes.", + "fields": { + "current": { + "name": "Current", + "description": "The maximum current used for the charging process. The value is depending on the DIP-switch settings and the used cable of the charging station." + } + } + }, + "enable": { + "name": "Enable", + "description": "Starts a charging process if charging station is authorized." + }, + "disable": { + "name": "Disable", + "description": "Stops the charging process if charging station is authorized." + }, + "set_failsafe": { + "name": "Set failsafe", + "description": "Sets the failsafe mode of the charging station. If all parameters are 0, the failsafe mode will be disabled.", + "fields": { + "failsafe_timeout": { + "name": "Failsafe timeout", + "description": "Timeout after which the failsafe mode is triggered, if set_current was not executed during this time." + }, + "failsafe_fallback": { + "name": "Failsafe fallback", + "description": "Fallback current to be set after timeout." + }, + "failsafe_persist": { + "name": "Failsafe persist", + "description": "If failsafe_persist is 0, the failsafe option is only until charging station reboot. If failsafe_persist is 1, the failsafe option will survive a reboot." + } + } + } + } +} diff --git a/homeassistant/components/kef/services.yaml b/homeassistant/components/kef/services.yaml index cf364edcf217a5..9c5e5083794131 100644 --- a/homeassistant/components/kef/services.yaml +++ b/homeassistant/components/kef/services.yaml @@ -1,14 +1,10 @@ update_dsp: - name: Update DSP - description: Update all DSP settings. target: entity: integration: kef domain: media_player set_mode: - name: Set mode - description: Set the mode of the speaker. target: entity: integration: kef @@ -16,36 +12,24 @@ set_mode: fields: desk_mode: - name: Desk mode - description: Desk mode. selector: boolean: wall_mode: - name: Wall mode - description: Wall mode. selector: boolean: phase_correction: - name: Phase correction - description: Phase correction. selector: boolean: high_pass: - name: High pass - description: High-pass mode". selector: boolean: sub_polarity: - name: Subwoofer polarity - description: Sub polarity. selector: select: options: - "-" - "+" bass_extension: - name: Base extension - description: Bass extension. selector: select: options: @@ -54,16 +38,12 @@ set_mode: - "Extra" set_desk_db: - name: Set desk dB - description: Set the "Desk mode" slider of the speaker in dB. target: entity: integration: kef domain: media_player fields: db_value: - name: dB value - description: Value of the slider example: 0.0 selector: number: @@ -73,16 +53,12 @@ set_desk_db: unit_of_measurement: dB set_wall_db: - name: Set wall dB - description: Set the "Wall mode" slider of the speaker in dB. target: entity: integration: kef domain: media_player fields: db_value: - name: dB value - description: Value of the slider. selector: number: min: -6 @@ -91,16 +67,12 @@ set_wall_db: unit_of_measurement: dB set_treble_db: - name: Set treble dB - description: Set desk the "Treble trim" slider of the speaker in dB. target: entity: integration: kef domain: media_player fields: db_value: - name: dB value - description: Value of the slider. selector: number: min: -2 @@ -109,16 +81,12 @@ set_treble_db: unit_of_measurement: dB set_high_hz: - name: Set high hertz - description: Set the "High-pass mode" slider of the speaker in Hz. target: entity: integration: kef domain: media_player fields: hz_value: - name: Hertz value - description: Value of the slider. selector: number: min: 50 @@ -127,16 +95,12 @@ set_high_hz: unit_of_measurement: Hz set_low_hz: - name: Set low Hertz - description: Set the "Sub out low-pass frequency" slider of the speaker in Hz. target: entity: integration: kef domain: media_player fields: hz_value: - name: Hertz value - description: Value of the slider. selector: number: min: 40 @@ -145,16 +109,12 @@ set_low_hz: unit_of_measurement: Hz set_sub_db: - name: Set subwoofer dB - description: Set the "Sub gain" slider of the speaker in dB. target: entity: integration: kef domain: media_player fields: db_value: - name: dB value - description: Value of the slider. selector: number: min: -10 diff --git a/homeassistant/components/kef/strings.json b/homeassistant/components/kef/strings.json new file mode 100644 index 00000000000000..7307caa6bb328f --- /dev/null +++ b/homeassistant/components/kef/strings.json @@ -0,0 +1,98 @@ +{ + "services": { + "update_dsp": { + "name": "Update DSP", + "description": "Updates all DSP settings." + }, + "set_mode": { + "name": "Set mode", + "description": "Sets the mode of the speaker.", + "fields": { + "desk_mode": { + "name": "Desk mode", + "description": "Desk mode." + }, + "wall_mode": { + "name": "Wall mode", + "description": "Wall mode." + }, + "phase_correction": { + "name": "Phase correction", + "description": "Phase correction." + }, + "high_pass": { + "name": "High pass", + "description": "High-pass mode\"." + }, + "sub_polarity": { + "name": "Subwoofer polarity", + "description": "Sub polarity." + }, + "bass_extension": { + "name": "Base extension", + "description": "Bass extension." + } + } + }, + "set_desk_db": { + "name": "Set desk dB", + "description": "Sets the \"Desk mode\" slider of the speaker in dB.", + "fields": { + "db_value": { + "name": "DB value", + "description": "Value of the slider." + } + } + }, + "set_wall_db": { + "name": "Set wall dB", + "description": "Sets the \"Wall mode\" slider of the speaker in dB.", + "fields": { + "db_value": { + "name": "DB value", + "description": "Value of the slider." + } + } + }, + "set_treble_db": { + "name": "Set treble dB", + "description": "Sets desk the \"Treble trim\" slider of the speaker in dB.", + "fields": { + "db_value": { + "name": "DB value", + "description": "Value of the slider." + } + } + }, + "set_high_hz": { + "name": "Set high hertz", + "description": "Sets the \"High-pass mode\" slider of the speaker in Hz.", + "fields": { + "hz_value": { + "name": "Hertz value", + "description": "Value of the slider." + } + } + }, + "set_low_hz": { + "name": "Sets low Hertz", + "description": "Set the \"Sub out low-pass frequency\" slider of the speaker in Hz.", + "fields": { + "hz_value": { + "name": "Hertz value", + "description": "Value of the slider." + } + } + }, + "set_sub_db": { + "name": "Sets subwoofer dB", + "description": "Set the \"Sub gain\" slider of the speaker in dB.", + "fields": { + "db_value": { + "name": "DB value", + "description": "Value of the slider." + } + } + } + } +} diff --git a/homeassistant/components/keyboard/services.yaml b/homeassistant/components/keyboard/services.yaml index 07f02959c395a1..b236f8eb80eb20 100644 --- a/homeassistant/components/keyboard/services.yaml +++ b/homeassistant/components/keyboard/services.yaml @@ -1,35 +1,6 @@ volume_up: - name: Volume up - description: - Simulates a key press of the "Volume Up" button on Home Assistant's host - machine - volume_down: - name: Volume down - description: - Simulates a key press of the "Volume Down" button on Home Assistant's host - machine - volume_mute: - name: Volume mute - description: - Simulates a key press of the "Volume Mute" button on Home Assistant's host - machine - media_play_pause: - name: Media play/pause - description: - Simulates a key press of the "Media Play/Pause" button on Home Assistant's - host machine - media_next_track: - name: Media next track - description: - Simulates a key press of the "Media Next Track" button on Home Assistant's - host machine - media_prev_track: - name: Media previous track - description: - Simulates a key press of the "Media Previous Track" button on Home - Assistant's host machine diff --git a/homeassistant/components/keyboard/strings.json b/homeassistant/components/keyboard/strings.json new file mode 100644 index 00000000000000..1b744cb7a71e0c --- /dev/null +++ b/homeassistant/components/keyboard/strings.json @@ -0,0 +1,28 @@ +{ + "services": { + "volume_up": { + "name": "Volume up", + "description": "Simulates a key press of the \"Volume Up\" button on Home Assistant's host machine." + }, + "volume_down": { + "name": "Volume down", + "description": "Simulates a key press of the \"Volume Down\" button on Home Assistant's host machine." + }, + "volume_mute": { + "name": "Volume mute", + "description": "Simulates a key press of the \"Volume Mute\" button on Home Assistant's host machine." + }, + "media_play_pause": { + "name": "Media play/pause", + "description": "Simulates a key press of the \"Media Play/Pause\" button on Home Assistant's host machine." + }, + "media_next_track": { + "name": "Media next track", + "description": "Simulates a key press of the \"Media Next Track\" button on Home Assistant's host machine." + }, + "media_prev_track": { + "name": "Media previous track", + "description": "Simulates a key press of the \"Media Previous Track\" button on Home Assistant's host machine." + } + } +} diff --git a/homeassistant/components/keymitt_ble/services.yaml b/homeassistant/components/keymitt_ble/services.yaml index c611577eb26d91..2be5c07c804c0e 100644 --- a/homeassistant/components/keymitt_ble/services.yaml +++ b/homeassistant/components/keymitt_ble/services.yaml @@ -1,17 +1,11 @@ calibrate: - name: Calibrate - description: Calibration - Set depth, press & hold duration, and operation mode. Warning - this will send a push command to the device fields: entity_id: - name: Entity - description: Name of entity to calibrate selector: entity: integration: keymitt_ble domain: switch depth: - name: Depth - description: Depth in percent example: 50 required: true selector: @@ -22,8 +16,6 @@ calibrate: max: 100 unit_of_measurement: "%" duration: - name: Duration - description: Duration in seconds example: 1 required: true selector: @@ -34,8 +26,6 @@ calibrate: max: 60 unit_of_measurement: seconds mode: - name: Mode - description: normal | invert | toggle example: "normal" required: true selector: diff --git a/homeassistant/components/keymitt_ble/strings.json b/homeassistant/components/keymitt_ble/strings.json index fd8e1f4825d294..57e7fc68582c8e 100644 --- a/homeassistant/components/keymitt_ble/strings.json +++ b/homeassistant/components/keymitt_ble/strings.json @@ -23,5 +23,29 @@ "unknown": "[%key:common::config_flow::error::unknown%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]" } + }, + "services": { + "calibrate": { + "name": "Calibrate", + "description": "Calibration - Set depth, press & hold duration, and operation mode. Warning - this will send a push command to the device.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Name of entity to calibrate." + }, + "depth": { + "name": "Depth", + "description": "Depth in percent." + }, + "duration": { + "name": "Duration", + "description": "Duration in seconds." + }, + "mode": { + "name": "Mode", + "description": "Normal | invert | toggle." + } + } + } } } diff --git a/homeassistant/components/knx/services.yaml b/homeassistant/components/knx/services.yaml index 0ad497a30a261c..813bf758eb0b04 100644 --- a/homeassistant/components/knx/services.yaml +++ b/homeassistant/components/knx/services.yaml @@ -1,111 +1,73 @@ send: - name: "Send to KNX bus" - description: "Send arbitrary data directly to the KNX bus." fields: address: - name: "Group address" - description: "Group address(es) to write to. Lists will send to multiple group addresses successively." required: true example: "1/1/0" selector: object: payload: - name: "Payload" - description: "Payload to send to the bus. Integers are treated as DPT 1/2/3 payloads. For DPTs > 6 bits send a list. Each value represents 1 octet (0-255). Pad with 0 to DPT byte length." required: true example: "[0, 4]" selector: object: type: - name: "Value type" - description: "If set, the payload will not be sent as raw bytes, but encoded as given DPT. KNX sensor types are valid values (see https://www.home-assistant.io/integrations/knx/#value-types)." required: false example: "temperature" selector: text: response: - name: "Send as Response" - description: "If set to `True`, the telegram will be sent as a `GroupValueResponse` instead of a `GroupValueWrite`." default: false selector: boolean: read: - name: "Read from KNX bus" - description: "Send GroupValueRead requests to the KNX bus. Response can be used from `knx_event` and will be processed in KNX entities." fields: address: - name: "Group address" - description: "Group address(es) to send read request to. Lists will read multiple group addresses." required: true example: "1/1/0" selector: object: event_register: - name: "Register knx_event" - description: "Add or remove group addresses to knx_event filter for triggering `knx_event`s. Only addresses added with this service can be removed." fields: address: - name: "Group address" - description: "Group address(es) that shall be added or removed. Lists are allowed." required: true example: "1/1/0" selector: object: type: - name: "Value type" - description: "If set, the payload will be decoded as given DPT in the event data `value` key. KNX sensor types are valid values (see https://www.home-assistant.io/integrations/knx/#value-types)." required: false example: "2byte_float" selector: text: remove: - name: "Remove event registration" - description: "If `True` the group address(es) will be removed." default: false selector: boolean: exposure_register: - name: "Expose to KNX bus" - description: "Add or remove exposures to KNX bus. Only exposures added with this service can be removed." fields: address: - name: "Group address" - description: "Group address state or attribute updates will be sent to. GroupValueRead requests will be answered. Per address only one exposure can be registered." required: true example: "1/1/0" selector: text: type: - name: "Value type" - description: "Telegrams will be encoded as given DPT. 'binary' and all KNX sensor types are valid values (see https://www.home-assistant.io/integrations/knx/#value-types)" required: true example: "percentU8" selector: text: entity_id: - name: "Entity" - description: "Entity id whose state or attribute shall be exposed." required: true selector: entity: attribute: - name: "Entity attribute" - description: "Attribute of the entity that shall be sent to the KNX bus. If not set the state will be sent. Eg. for a light the state is eigther “on” or “off” - with attribute you can expose its “brightness”." example: "brightness" selector: text: default: - name: "Default value" - description: "Default value to send to the bus if the state or attribute value is None. Eg. a light with state “off” has no brightness attribute so a default value of 0 could be used. If not set (or None) no value would be sent to the bus and a GroupReadRequest to the address would return the last known value." example: "0" selector: object: remove: - name: "Remove exposure" - description: "If `True` the exposure will be removed. Only `address` is required for removal." default: false selector: boolean: reload: - name: Reload - description: Reload the KNX integration. diff --git a/homeassistant/components/knx/strings.json b/homeassistant/components/knx/strings.json index cdd61379567d55..9a17fed506c652 100644 --- a/homeassistant/components/knx/strings.json +++ b/homeassistant/components/knx/strings.json @@ -288,5 +288,91 @@ "trigger_type": { "telegram": "Telegram sent or received" } + }, + "services": { + "send": { + "name": "Send to KNX bus", + "description": "Sends arbitrary data directly to the KNX bus.", + "fields": { + "address": { + "name": "Group address", + "description": "Group address(es) to write to. Lists will send to multiple group addresses successively." + }, + "payload": { + "name": "Payload", + "description": "Payload to send to the bus. Integers are treated as DPT 1/2/3 payloads. For DPTs > 6 bits send a list. Each value represents 1 octet (0-255). Pad with 0 to DPT byte length." + }, + "type": { + "name": "Value type", + "description": "If set, the payload will not be sent as raw bytes, but encoded as given DPT. KNX sensor types are valid values (see https://www.home-assistant.io/integrations/knx/#value-types)." + }, + "response": { + "name": "Send as Response", + "description": "If set to `True`, the telegram will be sent as a `GroupValueResponse` instead of a `GroupValueWrite`." + } + } + }, + "read": { + "name": "Reads from KNX bus", + "description": "Send GroupValueRead requests to the KNX bus. Response can be used from `knx_event` and will be processed in KNX entities.", + "fields": { + "address": { + "name": "Group address", + "description": "Group address(es) to send read request to. Lists will read multiple group addresses." + } + } + }, + "event_register": { + "name": "Registers knx_event", + "description": "Add or remove group addresses to knx_event filter for triggering `knx_event`s. Only addresses added with this service can be removed.", + "fields": { + "address": { + "name": "Group address", + "description": "Group address(es) that shall be added or removed. Lists are allowed." + }, + "type": { + "name": "Value type", + "description": "If set, the payload will be decoded as given DPT in the event data `value` key. KNX sensor types are valid values (see https://www.home-assistant.io/integrations/knx/#value-types)." + }, + "remove": { + "name": "Remove event registration", + "description": "If `True` the group address(es) will be removed." + } + } + }, + "exposure_register": { + "name": "Expose to KNX bus", + "description": "Adds or remove exposures to KNX bus. Only exposures added with this service can be removed.", + "fields": { + "address": { + "name": "Group address", + "description": "Group address state or attribute updates will be sent to. GroupValueRead requests will be answered. Per address only one exposure can be registered." + }, + "type": { + "name": "Value type", + "description": "Telegrams will be encoded as given DPT. 'binary' and all KNX sensor types are valid values (see https://www.home-assistant.io/integrations/knx/#value-types)." + }, + "entity_id": { + "name": "Entity", + "description": "Entity id whose state or attribute shall be exposed." + }, + "attribute": { + "name": "Entity attribute", + "description": "Attribute of the entity that shall be sent to the KNX bus. If not set the state will be sent. Eg. for a light the state is eigther \u201con\u201d or \u201coff\u201d - with attribute you can expose its \u201cbrightness\u201d." + }, + "default": { + "name": "Default value", + "description": "Default value to send to the bus if the state or attribute value is None. Eg. a light with state \u201coff\u201d has no brightness attribute so a default value of 0 could be used. If not set (or None) no value would be sent to the bus and a GroupReadRequest to the address would return the last known value." + }, + "remove": { + "name": "Remove exposure", + "description": "If `True` the exposure will be removed. Only `address` is required for removal." + } + } + }, + "reload": { + "name": "Reload", + "description": "Reloads the KNX integration." + } } } diff --git a/homeassistant/components/kodi/services.yaml b/homeassistant/components/kodi/services.yaml index cf6cdfc240db07..76ed0aca22d60e 100644 --- a/homeassistant/components/kodi/services.yaml +++ b/homeassistant/components/kodi/services.yaml @@ -1,50 +1,36 @@ # Describes the format for available Kodi services add_to_playlist: - name: Add to playlist - description: Add music to the default playlist (i.e. playlistid=0). target: entity: integration: kodi domain: media_player fields: media_type: - name: Media type - description: Media type identifier. It must be one of SONG or ALBUM. required: true example: ALBUM selector: text: media_id: - name: Media ID - description: Unique Id of the media entry to add (`songid` or albumid`). If not defined, `media_name` and `artist_name` are needed to search the Kodi music library. example: 123456 selector: text: media_name: - name: Media Name - description: Optional media name for filtering media. Can be 'ALL' when `media_type` is 'ALBUM' and `artist_name` is specified, to add all songs from one artist. example: "Highway to Hell" selector: text: artist_name: - name: Artist name - description: Optional artist name for filtering media. example: "AC/DC" selector: text: call_method: - name: Call method - description: "Call a Kodi JSONRPC API method with optional parameters. Results of the Kodi API call will be redirected in a Home Assistant event: `kodi_call_method_result`." target: entity: integration: kodi domain: media_player fields: method: - name: Method - description: Name of the Kodi JSONRPC API method to be called. required: true example: "VideoLibrary.GetRecentlyAddedEpisodes" selector: diff --git a/homeassistant/components/kodi/strings.json b/homeassistant/components/kodi/strings.json index 8097eb6336b75d..f7ee375f9902f0 100644 --- a/homeassistant/components/kodi/strings.json +++ b/homeassistant/components/kodi/strings.json @@ -46,5 +46,39 @@ "turn_on": "[%key:common::device_automation::action_type::turn_on%]", "turn_off": "[%key:common::device_automation::action_type::turn_off%]" } + }, + "services": { + "add_to_playlist": { + "name": "Add to playlist", + "description": "Adds music to the default playlist (i.e. playlistid=0).", + "fields": { + "media_type": { + "name": "Media type", + "description": "Media type identifier. It must be one of SONG or ALBUM." + }, + "media_id": { + "name": "Media ID", + "description": "Unique Id of the media entry to add (`songid` or albumid`). If not defined, `media_name` and `artist_name` are needed to search the Kodi music library." + }, + "media_name": { + "name": "Media name", + "description": "Optional media name for filtering media. Can be 'ALL' when `media_type` is 'ALBUM' and `artist_name` is specified, to add all songs from one artist." + }, + "artist_name": { + "name": "Artist name", + "description": "Optional artist name for filtering media." + } + } + }, + "call_method": { + "name": "Call method", + "description": "Calls a Kodi JSONRPC API method with optional parameters. Results of the Kodi API call will be redirected in a Home Assistant event: `kodi_call_method_result`.", + "fields": { + "method": { + "name": "Method", + "description": "Name of the Kodi JSONRPC API method to be called." + } + } + } } } From e8c292185289806efe5036c2771bf225bd58662f Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Wed, 12 Jul 2023 16:40:03 +0200 Subject: [PATCH 098/154] Add explicit device naming to Led BLE (#96421) --- homeassistant/components/led_ble/light.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/led_ble/light.py b/homeassistant/components/led_ble/light.py index 22a52e61b63aa1..94f445f1ec10d3 100644 --- a/homeassistant/components/led_ble/light.py +++ b/homeassistant/components/led_ble/light.py @@ -43,6 +43,7 @@ class LEDBLEEntity(CoordinatorEntity, LightEntity): _attr_supported_color_modes = {ColorMode.RGB, ColorMode.WHITE} _attr_has_entity_name = True + _attr_name = None _attr_supported_features = LightEntityFeature.EFFECT def __init__( From e513b7d0ebb3927ca66297661c22fb15e75fa599 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 12 Jul 2023 16:58:35 +0200 Subject: [PATCH 099/154] Add condition selector for blueprint (#96350) * Add condition selector for blueprint * Add tests and validation * Update comment --- homeassistant/helpers/selector.py | 21 +++++++++++++++++++++ tests/helpers/test_selector.py | 26 ++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/homeassistant/helpers/selector.py b/homeassistant/helpers/selector.py index abd4d2e623ee12..c996fcaf524f6e 100644 --- a/homeassistant/helpers/selector.py +++ b/homeassistant/helpers/selector.py @@ -453,6 +453,27 @@ def __call__(self, data: Any) -> int: return value +class ConditionSelectorConfig(TypedDict): + """Class to represent an action selector config.""" + + +@SELECTORS.register("condition") +class ConditionSelector(Selector[ConditionSelectorConfig]): + """Selector of an condition sequence (script syntax).""" + + selector_type = "condition" + + CONFIG_SCHEMA = vol.Schema({}) + + def __init__(self, config: ConditionSelectorConfig | None = None) -> None: + """Instantiate a selector.""" + super().__init__(config) + + def __call__(self, data: Any) -> Any: + """Validate the passed selection.""" + return vol.Schema(cv.CONDITIONS_SCHEMA)(data) + + class ConfigEntrySelectorConfig(TypedDict, total=False): """Class to represent a config entry selector config.""" diff --git a/tests/helpers/test_selector.py b/tests/helpers/test_selector.py index fd2dba4b08459e..09cf79116a0af2 100644 --- a/tests/helpers/test_selector.py +++ b/tests/helpers/test_selector.py @@ -1017,3 +1017,29 @@ def test_conversation_agent_selector_schema( ) -> None: """Test conversation agent selector.""" _test_selector("conversation_agent", schema, valid_selections, invalid_selections) + + +@pytest.mark.parametrize( + ("schema", "valid_selections", "invalid_selections"), + ( + ( + {}, + ( + [ + { + "condition": "numeric_state", + "entity_id": ["sensor.temperature"], + "below": 20, + } + ], + [], + ), + ("abc"), + ), + ), +) +def test_condition_selector_schema( + schema, valid_selections, invalid_selections +) -> None: + """Test condition sequence selector.""" + _test_selector("condition", schema, valid_selections, invalid_selections) From c5cd7e58979d32d602d7fa91762262ad771b2257 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 16:59:45 +0200 Subject: [PATCH 100/154] Migrate update services to support translations (#96395) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/update/services.yaml | 10 -------- homeassistant/components/update/strings.json | 24 +++++++++++++++++++ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/update/services.yaml b/homeassistant/components/update/services.yaml index 9b16dbd2713147..036af10150a0a2 100644 --- a/homeassistant/components/update/services.yaml +++ b/homeassistant/components/update/services.yaml @@ -1,34 +1,24 @@ install: - name: Install update - description: Install an update for this device or service target: entity: domain: update fields: version: - name: Version - description: Version to install, if omitted, the latest version will be installed. required: false example: "1.0.0" selector: text: backup: - name: Backup - description: Backup before installing the update, if supported by the integration. required: false selector: boolean: skip: - name: Skip update - description: Mark currently available update as skipped. target: entity: domain: update clear_skipped: - name: Clear skipped update - description: Removes the skipped version marker from an update. target: entity: domain: update diff --git a/homeassistant/components/update/strings.json b/homeassistant/components/update/strings.json index b69e0acf65e5f2..1d238d3dd513d7 100644 --- a/homeassistant/components/update/strings.json +++ b/homeassistant/components/update/strings.json @@ -14,5 +14,29 @@ "firmware": { "name": "Firmware" } + }, + "services": { + "install": { + "name": "Install update", + "description": "Installs an update for this device or service.", + "fields": { + "version": { + "name": "Version", + "description": "The version to install. If omitted, the latest version will be installed." + }, + "backup": { + "name": "Backup", + "description": "If supported by the integration, this creates a backup before starting the update ." + } + } + }, + "skip": { + "name": "Skip update", + "description": "Marks currently available update as skipped." + }, + "clear_skipped": { + "name": "Clear skipped update", + "description": "Removes the skipped version marker from an update." + } } } From b39660df3b40ba05ea8329220d257917ac29ae49 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 17:04:22 +0200 Subject: [PATCH 101/154] Migrate lovelace services to support translations (#96340) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/lovelace/services.yaml | 2 -- homeassistant/components/lovelace/strings.json | 6 ++++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/lovelace/services.yaml b/homeassistant/components/lovelace/services.yaml index f9fc5999da6d35..7cf6d8e40277ae 100644 --- a/homeassistant/components/lovelace/services.yaml +++ b/homeassistant/components/lovelace/services.yaml @@ -1,5 +1,3 @@ # Describes the format for available lovelace services reload_resources: - name: Reload resources - description: Reload Lovelace resources from YAML configuration diff --git a/homeassistant/components/lovelace/strings.json b/homeassistant/components/lovelace/strings.json index 87f8407d93c9e2..64718308325786 100644 --- a/homeassistant/components/lovelace/strings.json +++ b/homeassistant/components/lovelace/strings.json @@ -6,5 +6,11 @@ "resources": "Resources", "views": "Views" } + }, + "services": { + "reload_resources": { + "name": "Reload resources", + "description": "Reloads dashboard resources from the YAML-configuration." + } } } From d6771e6f8a928032422279cd1954fb420c80b092 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 17:12:22 +0200 Subject: [PATCH 102/154] Migrate input helpers services to support translations (#96392) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- .../components/input_boolean/services.yaml | 8 --- .../components/input_boolean/strings.json | 18 +++++++ .../components/input_button/services.yaml | 2 - .../components/input_button/strings.json | 6 +++ .../components/input_datetime/services.yaml | 14 ----- .../components/input_datetime/strings.json | 28 ++++++++++ .../components/input_number/services.yaml | 10 ---- .../components/input_number/strings.json | 24 +++++++++ .../components/input_select/services.yaml | 22 -------- .../components/input_select/strings.json | 54 +++++++++++++++++++ .../components/input_text/services.yaml | 6 --- .../components/input_text/strings.json | 16 ++++++ 12 files changed, 146 insertions(+), 62 deletions(-) diff --git a/homeassistant/components/input_boolean/services.yaml b/homeassistant/components/input_boolean/services.yaml index d294d61fd4d3e8..9de0368ba3598c 100644 --- a/homeassistant/components/input_boolean/services.yaml +++ b/homeassistant/components/input_boolean/services.yaml @@ -1,24 +1,16 @@ toggle: - name: Toggle - description: Toggle an input boolean target: entity: domain: input_boolean turn_off: - name: Turn off - description: Turn off an input boolean target: entity: domain: input_boolean turn_on: - name: Turn on - description: Turn on an input boolean target: entity: domain: input_boolean reload: - name: Reload - description: Reload the input_boolean configuration diff --git a/homeassistant/components/input_boolean/strings.json b/homeassistant/components/input_boolean/strings.json index d8e1e133f55a53..9288de04f2c1f5 100644 --- a/homeassistant/components/input_boolean/strings.json +++ b/homeassistant/components/input_boolean/strings.json @@ -17,5 +17,23 @@ } } } + }, + "services": { + "toggle": { + "name": "Toggle", + "description": "Toggles the helper on/off." + }, + "turn_off": { + "name": "Turn off", + "description": "Turns off the helper." + }, + "turn_on": { + "name": "Turn on", + "description": "Turns on the helper." + }, + "reload": { + "name": "Reload", + "description": "Reloads helpers from the YAML-configuration." + } } } diff --git a/homeassistant/components/input_button/services.yaml b/homeassistant/components/input_button/services.yaml index 899ead91cb56bc..7c57fcff272155 100644 --- a/homeassistant/components/input_button/services.yaml +++ b/homeassistant/components/input_button/services.yaml @@ -1,6 +1,4 @@ press: - name: Press - description: Press the input button entity. target: entity: domain: input_button diff --git a/homeassistant/components/input_button/strings.json b/homeassistant/components/input_button/strings.json index cfd616fd5e73d0..b51d04926f5d2d 100644 --- a/homeassistant/components/input_button/strings.json +++ b/homeassistant/components/input_button/strings.json @@ -13,5 +13,11 @@ } } } + }, + "services": { + "press": { + "name": "Press", + "description": "Mimics the physical button press on the device." + } } } diff --git a/homeassistant/components/input_datetime/services.yaml b/homeassistant/components/input_datetime/services.yaml index 51b1d6b00c14ae..386f0096a5f715 100644 --- a/homeassistant/components/input_datetime/services.yaml +++ b/homeassistant/components/input_datetime/services.yaml @@ -1,33 +1,21 @@ set_datetime: - name: Set - description: This can be used to dynamically set the date and/or time. target: entity: domain: input_datetime fields: date: - name: Date - description: The target date the entity should be set to. example: '"2019-04-20"' selector: text: time: - name: Time - description: The target time the entity should be set to. example: '"05:04:20"' selector: time: datetime: - name: Date & Time - description: The target date & time the entity should be set to. example: '"2019-04-20 05:04:20"' selector: text: timestamp: - name: Timestamp - description: - The target date & time the entity should be set to as expressed by a - UNIX timestamp. selector: number: min: 0 @@ -35,5 +23,3 @@ set_datetime: mode: box reload: - name: Reload - description: Reload the input_datetime configuration. diff --git a/homeassistant/components/input_datetime/strings.json b/homeassistant/components/input_datetime/strings.json index 0c3a4b0b0d2fde..f657508a4c4688 100644 --- a/homeassistant/components/input_datetime/strings.json +++ b/homeassistant/components/input_datetime/strings.json @@ -34,5 +34,33 @@ } } } + }, + "services": { + "set_datetime": { + "name": "Set", + "description": "Sets the date and/or time.", + "fields": { + "date": { + "name": "Date", + "description": "The target date." + }, + "time": { + "name": "Time", + "description": "The target time." + }, + "datetime": { + "name": "Date & time", + "description": "The target date & time." + }, + "timestamp": { + "name": "Timestamp", + "description": "The target date & time, expressed by a UNIX timestamp." + } + } + }, + "reload": { + "name": "Reload", + "description": "Reloads helpers from the YAML-configuration." + } } } diff --git a/homeassistant/components/input_number/services.yaml b/homeassistant/components/input_number/services.yaml index 41164a7ccf52f2..e5de48a1262479 100644 --- a/homeassistant/components/input_number/services.yaml +++ b/homeassistant/components/input_number/services.yaml @@ -1,27 +1,19 @@ decrement: - name: Decrement - description: Decrement the value of an input number entity by its stepping. target: entity: domain: input_number increment: - name: Increment - description: Increment the value of an input number entity by its stepping. target: entity: domain: input_number set_value: - name: Set - description: Set the value of an input number entity. target: entity: domain: input_number fields: value: - name: Value - description: The target value the entity should be set to. required: true selector: number: @@ -31,5 +23,3 @@ set_value: mode: box reload: - name: Reload - description: Reload the input_number configuration. diff --git a/homeassistant/components/input_number/strings.json b/homeassistant/components/input_number/strings.json index 11ed2f8bf10d7c..020544c5d4eaac 100644 --- a/homeassistant/components/input_number/strings.json +++ b/homeassistant/components/input_number/strings.json @@ -33,5 +33,29 @@ } } } + }, + "services": { + "decrement": { + "name": "Decrement", + "description": "Decrements the current value by 1 step." + }, + "increment": { + "name": "Increment", + "description": "Increments the value by 1 step." + }, + "set_value": { + "name": "Set", + "description": "Sets the value.", + "fields": { + "value": { + "name": "Value", + "description": "The target value." + } + } + }, + "reload": { + "name": "Reload", + "description": "Reloads helpers from the YAML-configuration." + } } } diff --git a/homeassistant/components/input_select/services.yaml b/homeassistant/components/input_select/services.yaml index 8b8828eaa92c3f..92279e58a5404c 100644 --- a/homeassistant/components/input_select/services.yaml +++ b/homeassistant/components/input_select/services.yaml @@ -1,75 +1,53 @@ select_next: - name: Next - description: Select the next options of an input select entity. target: entity: domain: input_select fields: cycle: - name: Cycle - description: If the option should cycle from the last to the first. default: true selector: boolean: select_option: - name: Select - description: Select an option of an input select entity. target: entity: domain: input_select fields: option: - name: Option - description: Option to be selected. required: true example: '"Item A"' selector: text: select_previous: - name: Previous - description: Select the previous options of an input select entity. target: entity: domain: input_select fields: cycle: - name: Cycle - description: If the option should cycle from the first to the last. default: true selector: boolean: select_first: - name: First - description: Select the first option of an input select entity. target: entity: domain: input_select select_last: - name: Last - description: Select the last option of an input select entity. target: entity: domain: input_select set_options: - name: Set options - description: Set the options of an input select entity. target: entity: domain: input_select fields: options: - name: Options - description: Options for the input select entity. required: true example: '["Item A", "Item B", "Item C"]' selector: object: reload: - name: Reload - description: Reload the input_select configuration. diff --git a/homeassistant/components/input_select/strings.json b/homeassistant/components/input_select/strings.json index f0dead7a1dd37f..68970933346509 100644 --- a/homeassistant/components/input_select/strings.json +++ b/homeassistant/components/input_select/strings.json @@ -16,5 +16,59 @@ } } } + }, + "services": { + "select_next": { + "name": "Next", + "description": "Select the next option.", + "fields": { + "cycle": { + "name": "Cycle", + "description": "If the option should cycle from the last to the first option on the list." + } + } + }, + "select_option": { + "name": "Select", + "description": "Selects an option.", + "fields": { + "option": { + "name": "Option", + "description": "Option to be selected." + } + } + }, + "select_previous": { + "name": "Previous", + "description": "Selects the previous option.", + "fields": { + "cycle": { + "name": "[%key:component::input_select::services::select_next::fields::cycle::name%]", + "description": "[%key:component::input_select::services::select_next::fields::cycle::description%]" + } + } + }, + "select_first": { + "name": "First", + "description": "Selects the first option." + }, + "select_last": { + "name": "Last", + "description": "Selects the last option." + }, + "set_options": { + "name": "Set options", + "description": "Sets the options.", + "fields": { + "options": { + "name": "Options", + "description": "List of options." + } + } + }, + "reload": { + "name": "Reload", + "description": "Reloads helpers from the YAML-configuration." + } } } diff --git a/homeassistant/components/input_text/services.yaml b/homeassistant/components/input_text/services.yaml index cf19e15d7ae119..6cb5c1352c66c7 100644 --- a/homeassistant/components/input_text/services.yaml +++ b/homeassistant/components/input_text/services.yaml @@ -1,18 +1,12 @@ set_value: - name: Set - description: Set the value of an input text entity. target: entity: domain: input_text fields: value: - name: Value - description: The target value the entity should be set to. required: true example: This is an example text selector: text: reload: - name: Reload - description: Reload the input_text configuration. diff --git a/homeassistant/components/input_text/strings.json b/homeassistant/components/input_text/strings.json index d713c395b67ed9..a4dc6d929f5fed 100644 --- a/homeassistant/components/input_text/strings.json +++ b/homeassistant/components/input_text/strings.json @@ -29,5 +29,21 @@ } } } + }, + "services": { + "set_value": { + "name": "Set", + "description": "Sets the value.", + "fields": { + "value": { + "name": "Value", + "description": "The target value." + } + } + }, + "reload": { + "name": "Reload", + "description": "Reloads helpers from the YAML-configuration." + } } } From d3eda12af4345e8b32530f5632947812adea5f7f Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 17:28:05 +0200 Subject: [PATCH 103/154] Migrate recorder services to support translations (#96409) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- .../components/recorder/services.yaml | 21 --------- .../components/recorder/strings.json | 46 +++++++++++++++++++ 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/homeassistant/components/recorder/services.yaml b/homeassistant/components/recorder/services.yaml index f099cede9f21b1..b74dcc2a4946e2 100644 --- a/homeassistant/components/recorder/services.yaml +++ b/homeassistant/components/recorder/services.yaml @@ -1,12 +1,8 @@ # Describes the format for available recorder services purge: - name: Purge - description: Start purge task - to clean up old data from your database. fields: keep_days: - name: Days to keep - description: Number of history days to keep in database after purge. selector: number: min: 0 @@ -14,28 +10,20 @@ purge: unit_of_measurement: days repack: - name: Repack - description: Attempt to save disk space by rewriting the entire database file. default: false selector: boolean: apply_filter: - name: Apply filter - description: Apply entity_id and event_type filter in addition to time based purge. default: false selector: boolean: purge_entities: - name: Purge Entities - description: Start purge task to remove specific entities from your database. target: entity: {} fields: domains: - name: Domains to remove - description: List the domains that need to be removed from the recorder database. example: "sun" required: false default: [] @@ -43,8 +31,6 @@ purge_entities: object: entity_globs: - name: Entity Globs to remove - description: List the glob patterns to select entities for removal from the recorder database. example: "domain*.object_id*" required: false default: [] @@ -52,8 +38,6 @@ purge_entities: object: keep_days: - name: Days to keep - description: Number of history days to keep in database of matching rows. The default of 0 days will remove all matching rows. default: 0 selector: number: @@ -62,9 +46,4 @@ purge_entities: unit_of_measurement: days disable: - name: Disable - description: Stop the recording of events and state changes - enable: - name: Enable - description: Start the recording of events and state changes diff --git a/homeassistant/components/recorder/strings.json b/homeassistant/components/recorder/strings.json index 7af67f10e25656..a55f13b27c4f73 100644 --- a/homeassistant/components/recorder/strings.json +++ b/homeassistant/components/recorder/strings.json @@ -13,5 +13,51 @@ "title": "Update MariaDB to {min_version} or later resolve a significant performance issue", "description": "Older versions of MariaDB suffer from a significant performance regression when retrieving history data or purging the database. Update to MariaDB version {min_version} or later and restart Home Assistant. If you are using the MariaDB core add-on, make sure to update it to the latest version." } + }, + "services": { + "purge": { + "name": "Purge", + "description": "Starts purge task - to clean up old data from your database.", + "fields": { + "keep_days": { + "name": "Days to keep", + "description": "Number of days to keep the data in the database. Starting today, counting backward. A value of `7` means that everything older than a week will be purged." + }, + "repack": { + "name": "Repack", + "description": "Attempt to save disk space by rewriting the entire database file." + }, + "apply_filter": { + "name": "Apply filter", + "description": "Applys `entity_id` and `event_type` filters in addition to time-based purge." + } + } + }, + "purge_entities": { + "name": "Purge entities", + "description": "Starts a purge task to remove the data related to specific entities from your database.", + "fields": { + "domains": { + "name": "Domains to remove", + "description": "List of domains for which the data needs to be removed from the recorder database." + }, + "entity_globs": { + "name": "Entity globs to remove", + "description": "List of glob patterns used to select the entities for which the data is to be removed from the recorder database." + }, + "keep_days": { + "name": "Days to keep", + "description": "Number of days to keep the data for rows matching the filter. Starting today, counting backward. A value of `7` means that everything older than a week will be purged. The default of 0 days will remove all matching rows immediately." + } + } + }, + "disable": { + "name": "Disable", + "description": "Stops the recording of events and state changes." + }, + "enable": { + "name": "Enable", + "description": "Starts the recording of events and state changes." + } } } From 848221a1d7c34aba5b11edabb63c4afc58d74d09 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 18:05:51 +0200 Subject: [PATCH 104/154] Migrate humidifier services to support translations (#96327) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- .../components/humidifier/services.yaml | 12 ------- .../components/humidifier/strings.json | 34 +++++++++++++++++++ 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/humidifier/services.yaml b/homeassistant/components/humidifier/services.yaml index d498f0a2c14cd2..75e34cf5049e33 100644 --- a/homeassistant/components/humidifier/services.yaml +++ b/homeassistant/components/humidifier/services.yaml @@ -1,8 +1,6 @@ # Describes the format for available humidifier services set_mode: - name: Set mode - description: Set mode for humidifier device. target: entity: domain: humidifier @@ -10,21 +8,17 @@ set_mode: - humidifier.HumidifierEntityFeature.MODES fields: mode: - description: New mode required: true example: "away" selector: text: set_humidity: - name: Set humidity - description: Set target humidity of humidifier device. target: entity: domain: humidifier fields: humidity: - description: New target humidity for humidifier device. required: true selector: number: @@ -33,22 +27,16 @@ set_humidity: unit_of_measurement: "%" turn_on: - name: Turn on - description: Turn humidifier device on. target: entity: domain: humidifier turn_off: - name: Turn off - description: Turn humidifier device off. target: entity: domain: humidifier toggle: - name: Toggle - description: Toggles a humidifier device. target: entity: domain: humidifier diff --git a/homeassistant/components/humidifier/strings.json b/homeassistant/components/humidifier/strings.json index 7512b2abec7bcf..d3cf946f5bf7cc 100644 --- a/homeassistant/components/humidifier/strings.json +++ b/homeassistant/components/humidifier/strings.json @@ -74,5 +74,39 @@ "humidifier": { "name": "[%key:component::humidifier::entity_component::_::name%]" } + }, + "services": { + "set_mode": { + "name": "Set mode", + "description": "Sets the humidifier operation mode.", + "fields": { + "mode": { + "name": "Mode", + "description": "Operation mode. For example, _normal_, _eco_, or _away_. For a list of possible values, refer to the integration documentation." + } + } + }, + "set_humidity": { + "name": "Set humidity", + "description": "Sets the target humidity.", + "fields": { + "humidity": { + "name": "Humidity", + "description": "Target humidity." + } + } + }, + "turn_on": { + "name": "Turn on", + "description": "Turns the humidifier on." + }, + "turn_off": { + "name": "Turn off", + "description": "Turns the humidifier off." + }, + "toggle": { + "name": "Toggle", + "description": "Toggles the humidifier on/off." + } } } From 06adace7ca76a875effa4b276b0f5634d568647b Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 18:06:16 +0200 Subject: [PATCH 105/154] Migrate vacuum services to support translations (#96417) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/vacuum/services.yaml | 30 --------- homeassistant/components/vacuum/strings.json | 62 +++++++++++++++++++ 2 files changed, 62 insertions(+), 30 deletions(-) diff --git a/homeassistant/components/vacuum/services.yaml b/homeassistant/components/vacuum/services.yaml index c517f1aeaaf913..aab35b4207739a 100644 --- a/homeassistant/components/vacuum/services.yaml +++ b/homeassistant/components/vacuum/services.yaml @@ -1,8 +1,6 @@ # Describes the format for available vacuum services turn_on: - name: Turn on - description: Start a new cleaning task. target: entity: domain: vacuum @@ -10,8 +8,6 @@ turn_on: - vacuum.VacuumEntityFeature.TURN_ON turn_off: - name: Turn off - description: Stop the current cleaning task and return to home. target: entity: domain: vacuum @@ -19,8 +15,6 @@ turn_off: - vacuum.VacuumEntityFeature.TURN_OFF stop: - name: Stop - description: Stop the current cleaning task. target: entity: domain: vacuum @@ -28,8 +22,6 @@ stop: - vacuum.VacuumEntityFeature.STOP locate: - name: Locate - description: Locate the vacuum cleaner robot. target: entity: domain: vacuum @@ -37,8 +29,6 @@ locate: - vacuum.VacuumEntityFeature.LOCATE start_pause: - name: Start/Pause - description: Start, pause, or resume the cleaning task. target: entity: domain: vacuum @@ -46,8 +36,6 @@ start_pause: - vacuum.VacuumEntityFeature.PAUSE start: - name: Start - description: Start or resume the cleaning task. target: entity: domain: vacuum @@ -55,8 +43,6 @@ start: - vacuum.VacuumEntityFeature.START pause: - name: Pause - description: Pause the cleaning task. target: entity: domain: vacuum @@ -64,8 +50,6 @@ pause: - vacuum.VacuumEntityFeature.PAUSE return_to_base: - name: Return to base - description: Tell the vacuum cleaner to return to its dock. target: entity: domain: vacuum @@ -73,45 +57,31 @@ return_to_base: - vacuum.VacuumEntityFeature.RETURN_HOME clean_spot: - name: Clean spot - description: Tell the vacuum cleaner to do a spot clean-up. target: entity: domain: vacuum send_command: - name: Send command - description: Send a raw command to the vacuum cleaner. target: entity: domain: vacuum fields: command: - name: Command - description: Command to execute. required: true example: "set_dnd_timer" selector: text: params: - name: Parameters - description: Parameters for the command. example: '{ "key": "value" }' selector: object: set_fan_speed: - name: Set fan speed - description: Set the fan speed of the vacuum cleaner. target: entity: domain: vacuum fields: fan_speed: - name: Fan speed - description: - Platform dependent vacuum cleaner fan speed, with speed steps, like - 'medium' or by percentage, between 0 and 100. required: true example: "low" selector: diff --git a/homeassistant/components/vacuum/strings.json b/homeassistant/components/vacuum/strings.json index 93ef1e8584caf5..3bdf650ddd38d1 100644 --- a/homeassistant/components/vacuum/strings.json +++ b/homeassistant/components/vacuum/strings.json @@ -34,5 +34,67 @@ "title": "The {platform} custom integration is using deprecated vacuum feature", "description": "The custom integration `{platform}` is extending the deprecated base class `VacuumEntity` instead of `StateVacuumEntity`.\n\nPlease report it to the author of the `{platform}` custom integration.\n\nOnce an updated version of `{platform}` is available, install it and restart Home Assistant to fix this issue." } + }, + "services": { + "turn_on": { + "name": "Turn on", + "description": "Starts a new cleaning task." + }, + "turn_off": { + "name": "Turn off", + "description": "Stops the current cleaning task and returns to its dock." + }, + "stop": { + "name": "Stop", + "description": "Stops the current cleaning task." + }, + "locate": { + "name": "Locate", + "description": "Locates the vacuum cleaner robot." + }, + "start_pause": { + "name": "Start/pause", + "description": "Starts, pauses, or resumes the cleaning task." + }, + "start": { + "name": "Start", + "description": "Starts or resumes the cleaning task." + }, + "pause": { + "name": "Pause", + "description": "Pauses the cleaning task." + }, + "return_to_base": { + "name": "Return to base", + "description": "Tells the vacuum cleaner to return to its dock." + }, + "clean_spot": { + "name": "Clean spot", + "description": "Tells the vacuum cleaner to do a spot clean-up." + }, + "send_command": { + "name": "Send command", + "description": "Sends a raw command to the vacuum cleaner.", + "fields": { + "command": { + "name": "Command", + "description": "Command to execute. The commands are integration-specific." + }, + "params": { + "name": "Parameters", + "description": "Parameters for the command. The parameters are integration-specific." + } + } + }, + "set_fan_speed": { + "name": "Set fan speed", + "description": "Sets the fan speed of the vacuum cleaner.", + "fields": { + "fan_speed": { + "name": "Fan speed", + "description": "Fan speed. The value depends on the integration. Some integrations have speed steps, like 'medium'. Some use a percentage, between 0 and 100." + } + } + } } } From 80eb4747ff6c943e8c3b7e4f52df1f21c394ab9c Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 18:06:31 +0200 Subject: [PATCH 106/154] Migrate remote services to support translations (#96410) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/remote/services.yaml | 38 -------- homeassistant/components/remote/strings.json | 86 +++++++++++++++++++ 2 files changed, 86 insertions(+), 38 deletions(-) diff --git a/homeassistant/components/remote/services.yaml b/homeassistant/components/remote/services.yaml index a2b648d9eb31a0..0d8ef63bfc3753 100644 --- a/homeassistant/components/remote/services.yaml +++ b/homeassistant/components/remote/services.yaml @@ -1,15 +1,11 @@ # Describes the format for available remote services turn_on: - name: Turn On - description: Sends the Power On Command. target: entity: domain: remote fields: activity: - name: Activity - description: Activity ID or Activity Name to start. example: "BedroomTV" filter: supported_features: @@ -18,50 +14,36 @@ turn_on: text: toggle: - name: Toggle - description: Toggles a device. target: entity: domain: remote turn_off: - name: Turn Off - description: Sends the Power Off Command. target: entity: domain: remote send_command: - name: Send Command - description: Sends a command or a list of commands to a device. target: entity: domain: remote fields: device: - name: Device - description: Device ID to send command to. example: "32756745" selector: text: command: - name: Command - description: A single command or a list of commands to send. required: true example: "Play" selector: object: num_repeats: - name: Repeats - description: The number of times you want to repeat the command(s). default: 1 selector: number: min: 0 max: 255 delay_secs: - name: Delay Seconds - description: The time you want to wait in between repeated commands. default: 0.4 selector: number: @@ -70,8 +52,6 @@ send_command: step: 0.1 unit_of_measurement: seconds hold_secs: - name: Hold Seconds - description: The time you want to have it held before the release is send. default: 0 selector: number: @@ -81,27 +61,19 @@ send_command: unit_of_measurement: seconds learn_command: - name: Learn Command - description: Learns a command or a list of commands from a device. target: entity: domain: remote fields: device: - name: Device - description: Device ID to learn command from. example: "television" selector: text: command: - name: Command - description: A single command or a list of commands to learn. example: "Turn on" selector: object: command_type: - name: Command Type - description: The type of command to be learned. default: "ir" selector: select: @@ -109,13 +81,9 @@ learn_command: - "ir" - "rf" alternative: - name: Alternative - description: If code must be stored as alternative (useful for discrete remotes). selector: boolean: timeout: - name: Timeout - description: Timeout for the command to be learned. selector: number: min: 0 @@ -124,21 +92,15 @@ learn_command: unit_of_measurement: seconds delete_command: - name: Delete Command - description: Deletes a command or a list of commands from the database. target: entity: domain: remote fields: device: - name: Device - description: Name of the device from which commands will be deleted. example: "television" selector: text: command: - name: Command - description: A single command or a list of commands to delete. required: true example: "Mute" selector: diff --git a/homeassistant/components/remote/strings.json b/homeassistant/components/remote/strings.json index bf8a669af50428..14331c5cded7b6 100644 --- a/homeassistant/components/remote/strings.json +++ b/homeassistant/components/remote/strings.json @@ -24,5 +24,91 @@ "on": "[%key:common::state::on%]" } } + }, + "services": { + "turn_on": { + "name": "Turn on", + "description": "Sends the power on command.", + "fields": { + "activity": { + "name": "Activity", + "description": "Activity ID or activity name to be started." + } + } + }, + "toggle": { + "name": "Toggle", + "description": "Toggles a device on/off." + }, + "turn_off": { + "name": "Turn off", + "description": "Turns the device off." + }, + "send_command": { + "name": "Send command", + "description": "Sends a command or a list of commands to a device.", + "fields": { + "device": { + "name": "Device", + "description": "Device ID to send command to." + }, + "command": { + "name": "Command", + "description": "A single command or a list of commands to send." + }, + "num_repeats": { + "name": "Repeats", + "description": "The number of times you want to repeat the commands." + }, + "delay_secs": { + "name": "Delay seconds", + "description": "The time you want to wait in between repeated commands." + }, + "hold_secs": { + "name": "Hold seconds", + "description": "The time you want to have it held before the release is send." + } + } + }, + "learn_command": { + "name": "Learn command", + "description": "Learns a command or a list of commands from a device.", + "fields": { + "device": { + "name": "Device", + "description": "Device ID to learn command from." + }, + "command": { + "name": "Command", + "description": "A single command or a list of commands to learn." + }, + "command_type": { + "name": "Command type", + "description": "The type of command to be learned." + }, + "alternative": { + "name": "Alternative", + "description": "If code must be stored as an alternative. This is useful for discrete codes. Discrete codes are used for toggles that only perform one function. For example, a code to only turn a device on. If it is on already, sending the code won't change the state." + }, + "timeout": { + "name": "Timeout", + "description": "Timeout for the command to be learned." + } + } + }, + "delete_command": { + "name": "Delete command", + "description": "Deletes a command or a list of commands from the database.", + "fields": { + "device": { + "name": "Device", + "description": "Device from which commands will be deleted." + }, + "command": { + "name": "Command", + "description": "The single command or the list of commands to be deleted." + } + } + } } } From 5792301cf1caf7c37635ff81842e89fe016c5163 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 18:16:30 +0200 Subject: [PATCH 107/154] Migrate lock services to support translations (#96416) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/lock/services.yaml | 12 -------- homeassistant/components/lock/strings.json | 32 +++++++++++++++++++++ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/lock/services.yaml b/homeassistant/components/lock/services.yaml index 992c58cf5f6c1b..c80517d1fe19c3 100644 --- a/homeassistant/components/lock/services.yaml +++ b/homeassistant/components/lock/services.yaml @@ -1,22 +1,16 @@ # Describes the format for available lock services lock: - name: Lock - description: Lock all or specified locks. target: entity: domain: lock fields: code: - name: Code - description: An optional code to lock the lock with. example: 1234 selector: text: open: - name: Open - description: Open all or specified locks. target: entity: domain: lock @@ -24,22 +18,16 @@ open: - lock.LockEntityFeature.OPEN fields: code: - name: Code - description: An optional code to open the lock with. example: 1234 selector: text: unlock: - name: Unlock - description: Unlock all or specified locks. target: entity: domain: lock fields: code: - name: Code - description: An optional code to unlock the lock with. example: 1234 selector: text: diff --git a/homeassistant/components/lock/strings.json b/homeassistant/components/lock/strings.json index da4b5217b86294..9e20b0cad2bd5d 100644 --- a/homeassistant/components/lock/strings.json +++ b/homeassistant/components/lock/strings.json @@ -34,5 +34,37 @@ } } } + }, + "services": { + "lock": { + "name": "Lock", + "description": "Locks a lock.", + "fields": { + "code": { + "name": "Code", + "description": "Code used to lock the lock." + } + } + }, + "open": { + "name": "Open", + "description": "Opens a lock.", + "fields": { + "code": { + "name": "[%key:component::lock::services::lock::fields::code::name%]", + "description": "Code used to open the lock." + } + } + }, + "unlock": { + "name": "Unlock", + "description": "Unlocks a lock.", + "fields": { + "code": { + "name": "[%key:component::lock::services::lock::fields::code::name%]", + "description": "Code used to unlock the lock." + } + } + } } } From 899adfa74c31b5bacedfe2fcd4c5b7cec3e4c695 Mon Sep 17 00:00:00 2001 From: RenierM26 <66512715+RenierM26@users.noreply.github.com> Date: Wed, 12 Jul 2023 18:33:56 +0200 Subject: [PATCH 108/154] Add Ezviz select entity (#93625) * Initial commit * Add select entity * coveragerc * Cleanup * Commit suggestions. * Raise issue before try except * Add translation key * Update camera.py * Update camera.py * Disable old sensor by default instead of removing. * Apply suggestions from code review Co-authored-by: G Johansson * IR fix flow * Fix conflict * run black --------- Co-authored-by: G Johansson --- .coveragerc | 1 + homeassistant/components/ezviz/__init__.py | 1 + homeassistant/components/ezviz/camera.py | 10 +++ homeassistant/components/ezviz/select.py | 99 +++++++++++++++++++++ homeassistant/components/ezviz/sensor.py | 5 +- homeassistant/components/ezviz/strings.json | 23 +++++ 6 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 homeassistant/components/ezviz/select.py diff --git a/.coveragerc b/.coveragerc index e10a23e9c31404..703523ed3648f8 100644 --- a/.coveragerc +++ b/.coveragerc @@ -321,6 +321,7 @@ omit = homeassistant/components/ezviz/coordinator.py homeassistant/components/ezviz/number.py homeassistant/components/ezviz/entity.py + homeassistant/components/ezviz/select.py homeassistant/components/ezviz/sensor.py homeassistant/components/ezviz/switch.py homeassistant/components/ezviz/update.py diff --git a/homeassistant/components/ezviz/__init__.py b/homeassistant/components/ezviz/__init__.py index 9386a407acb491..9aeba56360e8d8 100644 --- a/homeassistant/components/ezviz/__init__.py +++ b/homeassistant/components/ezviz/__init__.py @@ -37,6 +37,7 @@ Platform.CAMERA, Platform.LIGHT, Platform.NUMBER, + Platform.SELECT, Platform.SENSOR, Platform.SWITCH, Platform.UPDATE, diff --git a/homeassistant/components/ezviz/camera.py b/homeassistant/components/ezviz/camera.py index 6150a657c1ad7f..01e8425c13bbdc 100644 --- a/homeassistant/components/ezviz/camera.py +++ b/homeassistant/components/ezviz/camera.py @@ -290,6 +290,16 @@ def perform_wake_device(self) -> None: def perform_alarm_sound(self, level: int) -> None: """Enable/Disable movement sound alarm.""" + ir.async_create_issue( + self.hass, + DOMAIN, + "service_deprecation_alarm_sound_level", + breaks_in_ha_version="2024.2.0", + is_fixable=True, + is_persistent=True, + severity=ir.IssueSeverity.WARNING, + translation_key="service_deprecation_alarm_sound_level", + ) try: self.coordinator.ezviz_client.alarm_sound(self._serial, level, 1) except HTTPError as err: diff --git a/homeassistant/components/ezviz/select.py b/homeassistant/components/ezviz/select.py new file mode 100644 index 00000000000000..0f6a52ef578502 --- /dev/null +++ b/homeassistant/components/ezviz/select.py @@ -0,0 +1,99 @@ +"""Support for EZVIZ select controls.""" +from __future__ import annotations + +from dataclasses import dataclass + +from pyezviz.constants import DeviceSwitchType, SoundMode +from pyezviz.exceptions import HTTPError, PyEzvizError + +from homeassistant.components.select import SelectEntity, SelectEntityDescription +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import EntityCategory +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from .const import DATA_COORDINATOR, DOMAIN +from .coordinator import EzvizDataUpdateCoordinator +from .entity import EzvizEntity + +PARALLEL_UPDATES = 1 + + +@dataclass +class EzvizSelectEntityDescriptionMixin: + """Mixin values for EZVIZ Select entities.""" + + supported_switch: int + + +@dataclass +class EzvizSelectEntityDescription( + SelectEntityDescription, EzvizSelectEntityDescriptionMixin +): + """Describe a EZVIZ Select entity.""" + + +SELECT_TYPE = EzvizSelectEntityDescription( + key="alarm_sound_mod", + translation_key="alarm_sound_mode", + icon="mdi:alarm", + entity_category=EntityCategory.CONFIG, + options=["soft", "intensive", "silent"], + supported_switch=DeviceSwitchType.ALARM_TONE.value, +) + + +async def async_setup_entry( + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback +) -> None: + """Set up EZVIZ select entities based on a config entry.""" + coordinator: EzvizDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id][ + DATA_COORDINATOR + ] + + async_add_entities( + EzvizSensor(coordinator, camera) + for camera in coordinator.data + for switch in coordinator.data[camera]["switches"] + if switch == SELECT_TYPE.supported_switch + ) + + +class EzvizSensor(EzvizEntity, SelectEntity): + """Representation of a EZVIZ select entity.""" + + _attr_has_entity_name = True + + def __init__( + self, + coordinator: EzvizDataUpdateCoordinator, + serial: str, + ) -> None: + """Initialize the sensor.""" + super().__init__(coordinator, serial) + self._attr_unique_id = f"{serial}_{SELECT_TYPE.key}" + self.entity_description = SELECT_TYPE + + @property + def current_option(self) -> str | None: + """Return the selected entity option to represent the entity state.""" + sound_mode_value = getattr( + SoundMode, self.data[self.entity_description.key] + ).value + if sound_mode_value in [0, 1, 2]: + return self.options[sound_mode_value] + + return None + + def select_option(self, option: str) -> None: + """Change the selected option.""" + sound_mode_value = self.options.index(option) + + try: + self.coordinator.ezviz_client.alarm_sound(self._serial, sound_mode_value, 1) + + except (HTTPError, PyEzvizError) as err: + raise HomeAssistantError( + f"Cannot set Warning sound level for {self.entity_id}" + ) from err diff --git a/homeassistant/components/ezviz/sensor.py b/homeassistant/components/ezviz/sensor.py index 11412c1fc70d07..075fe6bd6d1b7d 100644 --- a/homeassistant/components/ezviz/sensor.py +++ b/homeassistant/components/ezviz/sensor.py @@ -24,7 +24,10 @@ native_unit_of_measurement=PERCENTAGE, device_class=SensorDeviceClass.BATTERY, ), - "alarm_sound_mod": SensorEntityDescription(key="alarm_sound_mod"), + "alarm_sound_mod": SensorEntityDescription( + key="alarm_sound_mod", + entity_registry_enabled_default=False, + ), "last_alarm_time": SensorEntityDescription(key="last_alarm_time"), "Seconds_Last_Trigger": SensorEntityDescription( key="Seconds_Last_Trigger", diff --git a/homeassistant/components/ezviz/strings.json b/homeassistant/components/ezviz/strings.json index 5355fcc377ca3a..aec1f892b1fbc2 100644 --- a/homeassistant/components/ezviz/strings.json +++ b/homeassistant/components/ezviz/strings.json @@ -70,6 +70,29 @@ } } } + }, + "service_deprecation_alarm_sound_level": { + "title": "Ezviz Alarm sound level service is being removed", + "fix_flow": { + "step": { + "confirm": { + "title": "[%key:component::ezviz::issues::service_deprecation_alarm_sound_level::title%]", + "description": "Ezviz Alarm sound level service is deprecated and will be removed in Home Assistant 2024.2.\nTo set the Alarm sound level, you can instead use the `select.select_option` service targetting the Warning sound entity.\n\nPlease remove the use of this service from your automations and scripts and select **submit** to close this issue." + } + } + } + } + }, + "entity": { + "select": { + "alarm_sound_mode": { + "name": "Warning sound", + "state": { + "soft": "Soft", + "intensive": "Intensive", + "silent": "Silent" + } + } } }, "services": { From c67a1a326f8da183bec50b21807b03e2689d940e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 12 Jul 2023 06:39:32 -1000 Subject: [PATCH 109/154] Improve chances of recovering stuck down bluetooth adapters (#96382) --- homeassistant/components/bluetooth/manifest.json | 4 ++-- homeassistant/components/bluetooth/scanner.py | 1 + homeassistant/package_constraints.txt | 4 ++-- requirements_all.txt | 4 ++-- requirements_test_all.txt | 4 ++-- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/bluetooth/manifest.json b/homeassistant/components/bluetooth/manifest.json index dbe8ac3f1ab7df..bed677ebd306f0 100644 --- a/homeassistant/components/bluetooth/manifest.json +++ b/homeassistant/components/bluetooth/manifest.json @@ -16,8 +16,8 @@ "requirements": [ "bleak==0.20.2", "bleak-retry-connector==3.0.2", - "bluetooth-adapters==0.15.3", - "bluetooth-auto-recovery==1.2.0", + "bluetooth-adapters==0.16.0", + "bluetooth-auto-recovery==1.2.1", "bluetooth-data-tools==1.3.0", "dbus-fast==1.86.0" ] diff --git a/homeassistant/components/bluetooth/scanner.py b/homeassistant/components/bluetooth/scanner.py index 911862a4221f6c..35efbdf3cbe035 100644 --- a/homeassistant/components/bluetooth/scanner.py +++ b/homeassistant/components/bluetooth/scanner.py @@ -53,6 +53,7 @@ "org.bluez.Error.Failed", "org.bluez.Error.InProgress", "org.bluez.Error.NotReady", + "not found", ] # When the adapter is still initializing, the scanner will raise an exception diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index b82a7315648f40..8ae3ba06985ba3 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -10,8 +10,8 @@ awesomeversion==22.9.0 bcrypt==4.0.1 bleak-retry-connector==3.0.2 bleak==0.20.2 -bluetooth-adapters==0.15.3 -bluetooth-auto-recovery==1.2.0 +bluetooth-adapters==0.16.0 +bluetooth-auto-recovery==1.2.1 bluetooth-data-tools==1.3.0 certifi>=2021.5.30 ciso8601==2.3.0 diff --git a/requirements_all.txt b/requirements_all.txt index d33f01b34be376..26d4911dddaad0 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -525,10 +525,10 @@ bluemaestro-ble==0.2.3 # bluepy==1.3.0 # homeassistant.components.bluetooth -bluetooth-adapters==0.15.3 +bluetooth-adapters==0.16.0 # homeassistant.components.bluetooth -bluetooth-auto-recovery==1.2.0 +bluetooth-auto-recovery==1.2.1 # homeassistant.components.bluetooth # homeassistant.components.esphome diff --git a/requirements_test_all.txt b/requirements_test_all.txt index f35021c3e006af..864938446e8d7a 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -439,10 +439,10 @@ blinkpy==0.21.0 bluemaestro-ble==0.2.3 # homeassistant.components.bluetooth -bluetooth-adapters==0.15.3 +bluetooth-adapters==0.16.0 # homeassistant.components.bluetooth -bluetooth-auto-recovery==1.2.0 +bluetooth-auto-recovery==1.2.1 # homeassistant.components.bluetooth # homeassistant.components.esphome From 7021daf9fba7d8c9360c0bc8d4361b05d92873c9 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 18:55:22 +0200 Subject: [PATCH 110/154] Migrate select services to support translations (#96411) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/select/services.yaml | 16 -------- homeassistant/components/select/strings.json | 40 +++++++++++++++++++ 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/homeassistant/components/select/services.yaml b/homeassistant/components/select/services.yaml index 8fb55936fc933a..dc6d4c6815a562 100644 --- a/homeassistant/components/select/services.yaml +++ b/homeassistant/components/select/services.yaml @@ -1,56 +1,40 @@ select_first: - name: First - description: Select the first option of an select entity. target: entity: domain: select select_last: - name: Last - description: Select the last option of an select entity. target: entity: domain: select select_next: - name: Next - description: Select the next options of an select entity. target: entity: domain: select fields: cycle: - name: Cycle - description: If the option should cycle from the last to the first. default: true selector: boolean: select_option: - name: Select - description: Select an option of an select entity. target: entity: domain: select fields: option: - name: Option - description: Option to be selected. required: true example: '"Item A"' selector: text: select_previous: - name: Previous - description: Select the previous options of an select entity. target: entity: domain: select fields: cycle: - name: Cycle - description: If the option should cycle from the first to the last. default: true selector: boolean: diff --git a/homeassistant/components/select/strings.json b/homeassistant/components/select/strings.json index 9080b940b2a5f7..d058ff6e6f2c7f 100644 --- a/homeassistant/components/select/strings.json +++ b/homeassistant/components/select/strings.json @@ -24,5 +24,45 @@ } } } + }, + "services": { + "select_first": { + "name": "First", + "description": "Selects the first option." + }, + "select_last": { + "name": "Last", + "description": "Selects the last option." + }, + "select_next": { + "name": "Next", + "description": "Selects the next option.", + "fields": { + "cycle": { + "name": "Cycle", + "description": "If the option should cycle from the last to the first." + } + } + }, + "select_option": { + "name": "Select", + "description": "Selects an option.", + "fields": { + "option": { + "name": "Option", + "description": "Option to be selected." + } + } + }, + "select_previous": { + "name": "Previous", + "description": "Selects the previous option.", + "fields": { + "cycle": { + "name": "Cycle", + "description": "If the option should cycle from the first to the last." + } + } + } } } From 021aaa999498b7f0cbed9f427612947a7d369da1 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 18:55:34 +0200 Subject: [PATCH 111/154] Migrate tts services to support translations (#96412) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/tts/services.yaml | 30 ----------- homeassistant/components/tts/strings.json | 60 ++++++++++++++++++++++ 2 files changed, 60 insertions(+), 30 deletions(-) create mode 100644 homeassistant/components/tts/strings.json diff --git a/homeassistant/components/tts/services.yaml b/homeassistant/components/tts/services.yaml index 99e0bcca4d4b31..03b176eaab3f3b 100644 --- a/homeassistant/components/tts/services.yaml +++ b/homeassistant/components/tts/services.yaml @@ -1,88 +1,58 @@ # Describes the format for available TTS services say: - name: Say a TTS message - description: Say something using text-to-speech on a media player. fields: entity_id: - name: Entity - description: Name(s) of media player entities. required: true selector: entity: domain: media_player message: - name: Message - description: Text to speak on devices. example: "My name is hanna" required: true selector: text: cache: - name: Cache - description: Control file cache of this message. default: false selector: boolean: language: - name: Language - description: Language to use for speech generation. example: "ru" selector: text: options: - name: Options - description: - A dictionary containing platform-specific options. Optional depending on - the platform. advanced: true example: platform specific selector: object: speak: - name: Speak - description: Speak something using text-to-speech on a media player. target: entity: domain: tts fields: media_player_entity_id: - name: Media Player Entity - description: Name(s) of media player entities. required: true selector: entity: domain: media_player message: - name: Message - description: Text to speak on devices. example: "My name is hanna" required: true selector: text: cache: - name: Cache - description: Control file cache of this message. default: true selector: boolean: language: - name: Language - description: Language to use for speech generation. example: "ru" selector: text: options: - name: Options - description: - A dictionary containing platform-specific options. Optional depending on - the platform. advanced: true example: platform specific selector: object: clear_cache: - name: Clear TTS cache - description: Remove all text-to-speech cache files and RAM cache. diff --git a/homeassistant/components/tts/strings.json b/homeassistant/components/tts/strings.json new file mode 100644 index 00000000000000..2f0208ef8b57b4 --- /dev/null +++ b/homeassistant/components/tts/strings.json @@ -0,0 +1,60 @@ +{ + "services": { + "say": { + "name": "Say a TTS message", + "description": "Says something using text-to-speech on a media player.", + "fields": { + "entity_id": { + "name": "Entity", + "description": "Media players to play the message." + }, + "message": { + "name": "Message", + "description": "The text you want to convert into speech so that you can listen to it on your device." + }, + "cache": { + "name": "Cache", + "description": "Stores this message locally so that when the text is requested again, the output can be produced more quickly." + }, + "language": { + "name": "Language", + "description": "Language to use for speech generation." + }, + "options": { + "name": "Options", + "description": "A dictionary containing integration-specific options." + } + } + }, + "speak": { + "name": "Speak", + "description": "Speaks something using text-to-speech on a media player.", + "fields": { + "media_player_entity_id": { + "name": "Media player entity", + "description": "Media players to play the message." + }, + "message": { + "name": "[%key:component::tts::services::say::fields::message::name%]", + "description": "[%key:component::tts::services::say::fields::message::description%]" + }, + "cache": { + "name": "[%key:component::tts::services::say::fields::cache::name%]", + "description": "[%key:component::tts::services::say::fields::cache::description%]" + }, + "language": { + "name": "[%key:component::tts::services::say::fields::language::name%]", + "description": "[%key:component::tts::services::say::fields::language::description%]" + }, + "options": { + "name": "[%key:component::tts::services::say::fields::options::name%]", + "description": "[%key:component::tts::services::say::fields::options::description%]" + } + } + }, + "clear_cache": { + "name": "Clear TTS cache", + "description": "Removes all cached text-to-speech files and purges the memory." + } + } +} From 728a5ff99b4e87aef6c4994bc21ce862ce6afbbc Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 18:56:08 +0200 Subject: [PATCH 112/154] Migrate system_log services to support translations (#96398) --- .../components/system_log/services.yaml | 28 +++----------- .../components/system_log/strings.json | 37 +++++++++++++++++++ 2 files changed, 43 insertions(+), 22 deletions(-) create mode 100644 homeassistant/components/system_log/strings.json diff --git a/homeassistant/components/system_log/services.yaml b/homeassistant/components/system_log/services.yaml index 0f9ae61ba4c8dd..9ab3bb6bce3203 100644 --- a/homeassistant/components/system_log/services.yaml +++ b/homeassistant/components/system_log/services.yaml @@ -1,39 +1,23 @@ clear: - name: Clear all - description: Clear all log entries. - write: - name: Write - description: Write log entry. fields: message: - name: Message - description: Message to log. required: true example: Something went wrong selector: text: level: - name: Level - description: "Log level." default: error selector: select: options: - - label: "Debug" - value: "debug" - - label: "Info" - value: "info" - - label: "Warning" - value: "warning" - - label: "Error" - value: "error" - - label: "Critical" - value: "critical" + - "debug" + - "info" + - "warning" + - "error" + - "critical" + translation_key: level logger: - name: Logger - description: Logger name under which to log the message. Defaults to - 'system_log.external'. example: mycomponent.myplatform selector: text: diff --git a/homeassistant/components/system_log/strings.json b/homeassistant/components/system_log/strings.json new file mode 100644 index 00000000000000..ed1ca79fe0795f --- /dev/null +++ b/homeassistant/components/system_log/strings.json @@ -0,0 +1,37 @@ +{ + "services": { + "clear": { + "name": "Clear all", + "description": "Clears all log entries." + }, + "write": { + "name": "Write", + "description": "Write log entry.", + "fields": { + "message": { + "name": "Message", + "description": "Message to log." + }, + "level": { + "name": "Level", + "description": "Log level." + }, + "logger": { + "name": "Logger", + "description": "Logger name under which to log the message. Defaults to `system_log.external`." + } + } + } + }, + "selector": { + "level": { + "options": { + "debug": "Debug", + "info": "Info", + "warning": "Warning", + "error": "Error", + "critical": "Critical" + } + } + } +} From 11cd7692a13daba35d8eab3745b6d7a0997e4896 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 19:58:08 +0200 Subject: [PATCH 113/154] Migrate group services to support translations (#96369) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> Co-authored-by: Joost Lekkerkerker --- homeassistant/components/group/services.yaml | 23 --------- homeassistant/components/group/strings.json | 50 ++++++++++++++++++++ 2 files changed, 50 insertions(+), 23 deletions(-) diff --git a/homeassistant/components/group/services.yaml b/homeassistant/components/group/services.yaml index fdb1a1af014912..e5ac921cc77da9 100644 --- a/homeassistant/components/group/services.yaml +++ b/homeassistant/components/group/services.yaml @@ -1,62 +1,39 @@ # Describes the format for available group services reload: - name: Reload - description: Reload group configuration, entities, and notify services. - set: - name: Set - description: Create/Update a user group. fields: object_id: - name: Object ID - description: Group id and part of entity id. required: true example: "test_group" selector: text: name: - name: Name - description: Name of group example: "My test group" selector: text: icon: - name: Icon - description: Name of icon for the group. example: "mdi:camera" selector: icon: entities: - name: Entities - description: List of all members in the group. Not compatible with 'delta'. example: domain.entity_id1, domain.entity_id2 selector: object: add_entities: - name: Add Entities - description: List of members that will change on group listening. example: domain.entity_id1, domain.entity_id2 selector: object: remove_entities: - name: Remove Entities - description: List of members that will be removed from group listening. example: domain.entity_id1, domain.entity_id2 selector: object: all: - name: All - description: Enable this option if the group should only turn on when all entities are on. selector: boolean: remove: - name: Remove - description: Remove a user group. fields: object_id: - name: Object ID - description: Group id and part of entity id. required: true example: "test_group" selector: diff --git a/homeassistant/components/group/strings.json b/homeassistant/components/group/strings.json index 192823cef6515b..7b49eaf4186356 100644 --- a/homeassistant/components/group/strings.json +++ b/homeassistant/components/group/strings.json @@ -190,5 +190,55 @@ "product": "Product" } } + }, + "services": { + "reload": { + "name": "Reload", + "description": "Reloads group configuration, entities, and notify services from YAML-configuration." + }, + "set": { + "name": "Set", + "description": "Creates/Updates a user group.", + "fields": { + "object_id": { + "name": "Object ID", + "description": "Object ID of this group. This object ID is used as part of the entity ID. Entity ID format: [domain].[object_id]." + }, + "name": { + "name": "Name", + "description": "Name of the group." + }, + "icon": { + "name": "Icon", + "description": "Name of the icon for the group." + }, + "entities": { + "name": "Entities", + "description": "List of all members in the group. Cannot be used in combination with `Add entities` or `Remove entities`." + }, + "add_entities": { + "name": "Add entities", + "description": "List of members to be added to the group. Cannot be used in combination with `Entities` or `Remove entities`." + }, + "remove_entities": { + "name": "Remove entities", + "description": "List of members to be removed from a group. Cannot be used in combination with `Entities` or `Add entities`." + }, + "all": { + "name": "All", + "description": "Enable this option if the group should only be used when all entities are in state `on`." + } + } + }, + "remove": { + "name": "Remove", + "description": "Removes a group.", + "fields": { + "object_id": { + "name": "Object ID", + "description": "Object ID of this group. This object ID is used as part of the entity ID. Entity ID format: [domain].[object_id]." + } + } + } } } From 273e80cc456c47e0da515f685d888ada48ee49da Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 20:24:21 +0200 Subject: [PATCH 114/154] Migrate text services to support translations (#96397) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/text/services.yaml | 4 ---- homeassistant/components/text/strings.json | 12 ++++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/text/services.yaml b/homeassistant/components/text/services.yaml index 00dd0ecafd28e0..b8461037b8bd18 100644 --- a/homeassistant/components/text/services.yaml +++ b/homeassistant/components/text/services.yaml @@ -1,13 +1,9 @@ set_value: - name: Set value - description: Set value of a text entity. target: entity: domain: text fields: value: - name: Value - description: Value to set. required: true example: "Hello world!" selector: diff --git a/homeassistant/components/text/strings.json b/homeassistant/components/text/strings.json index 034f1ab315b820..e6b3d99ced4a5d 100644 --- a/homeassistant/components/text/strings.json +++ b/homeassistant/components/text/strings.json @@ -27,5 +27,17 @@ } } } + }, + "services": { + "set_value": { + "name": "Set value", + "description": "Sets the value.", + "fields": { + "value": { + "name": "Value", + "description": "Enter your text." + } + } + } } } From a96ee22afa243c410cc715314b02837fd41343c1 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 20:37:45 +0200 Subject: [PATCH 115/154] Migrate notify services to support translations (#96413) * Migrate notify services to support translations * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/notify/services.yaml | 24 ---------- homeassistant/components/notify/strings.json | 46 ++++++++++++++++++- 2 files changed, 45 insertions(+), 25 deletions(-) diff --git a/homeassistant/components/notify/services.yaml b/homeassistant/components/notify/services.yaml index 9311acf2ba9536..8d053e3af5835f 100644 --- a/homeassistant/components/notify/services.yaml +++ b/homeassistant/components/notify/services.yaml @@ -1,61 +1,37 @@ # Describes the format for available notification services notify: - name: Send a notification - description: Sends a notification message to selected notify platforms. fields: message: - name: Message - description: Message body of the notification. required: true example: The garage door has been open for 10 minutes. selector: text: title: - name: Title - description: Title for your notification. example: "Your Garage Door Friend" selector: text: target: - name: Target - description: - An array of targets to send the notification to. Optional depending on - the platform. example: platform specific selector: object: data: - name: Data - description: - Extended information for notification. Optional depending on the - platform. example: platform specific selector: object: persistent_notification: - name: Send a persistent notification - description: Sends a notification that is visible in the front-end. fields: message: - name: Message - description: Message body of the notification. required: true example: The garage door has been open for 10 minutes. selector: text: title: - name: Title - description: Title for your notification. example: "Your Garage Door Friend" selector: text: data: - name: Data - description: - Extended information for notification. Optional depending on the - platform. example: platform specific selector: object: diff --git a/homeassistant/components/notify/strings.json b/homeassistant/components/notify/strings.json index 02027a84d8f4a4..cff7b265c37d7b 100644 --- a/homeassistant/components/notify/strings.json +++ b/homeassistant/components/notify/strings.json @@ -1 +1,45 @@ -{ "title": "Notifications" } +{ + "title": "Notifications", + "services": { + "notify": { + "name": "Send a notification", + "description": "Sends a notification message to selected targets.", + "fields": { + "message": { + "name": "Message", + "description": "Message body of the notification." + }, + "title": { + "name": "Title", + "description": "Title for your notification." + }, + "target": { + "name": "Target", + "description": "Some integrations allow you to specify the targets that receive the notification. For more information, refer to the integration documentation." + }, + "data": { + "name": "Data", + "description": "Some integrations provide extended functionality. For information on how to use _data_, refer to the integration documentation." + } + } + }, + "persistent_notification": { + "name": "Send a persistent notification", + "description": "Sends a notification that is visible in the **Notifications** panel.", + "fields": { + "message": { + "name": "Message", + "description": "Message body of the notification." + }, + "title": { + "name": "Title", + "description": "Title of the notification." + }, + "data": { + "name": "Data", + "description": "Some integrations provide extended functionality. For information on how to use _data_, refer to the integration documentation.." + } + } + } + } +} From e95c4f7e65f9d6dbc6df868ba1b78cff36712eac Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 12 Jul 2023 20:49:36 +0200 Subject: [PATCH 116/154] Migrate zha services to support translations (#96418) Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/zha/services.yaml | 132 ----------- homeassistant/components/zha/strings.json | 262 ++++++++++++++++++++- 2 files changed, 260 insertions(+), 134 deletions(-) diff --git a/homeassistant/components/zha/services.yaml b/homeassistant/components/zha/services.yaml index 132dae6e745a82..027653a4a6fdb9 100644 --- a/homeassistant/components/zha/services.yaml +++ b/homeassistant/components/zha/services.yaml @@ -1,12 +1,8 @@ # Describes the format for available zha services permit: - name: Permit - description: Allow nodes to join the Zigbee network. fields: duration: - name: Duration - description: Time to permit joins, in seconds default: 60 selector: number: @@ -14,73 +10,46 @@ permit: max: 254 unit_of_measurement: seconds ieee: - name: IEEE - description: IEEE address of the node permitting new joins example: "00:0d:6f:00:05:7d:2d:34" selector: text: source_ieee: - name: Source IEEE - description: IEEE address of the joining device (must be used with install code) example: "00:0a:bf:00:01:10:23:35" selector: text: install_code: - name: Install Code - description: Install code of the joining device (must be used with source_ieee) example: "1234-5678-1234-5678-AABB-CCDD-AABB-CCDD-EEFF" selector: text: qr_code: - name: QR Code - description: value of the QR install code (different between vendors) example: "Z:000D6FFFFED4163B$I:52797BF4A5084DAA8E1712B61741CA024051" selector: text: remove: - name: Remove - description: Remove a node from the Zigbee network. fields: ieee: - name: IEEE - description: IEEE address of the node to remove required: true example: "00:0d:6f:00:05:7d:2d:34" selector: text: reconfigure_device: - name: Reconfigure device - description: >- - Reconfigure ZHA device (heal device). Use this if you are having issues - with the device. If the device in question is a battery powered device - please ensure it is awake and accepting commands when you use this - service. fields: ieee: - name: IEEE - description: IEEE address of the device to reconfigure required: true example: "00:0d:6f:00:05:7d:2d:34" selector: text: set_zigbee_cluster_attribute: - name: Set zigbee cluster attribute - description: >- - Set attribute value for the specified cluster on the specified entity. fields: ieee: - name: IEEE - description: IEEE address for the device required: true example: "00:0d:6f:00:05:7d:2d:34" selector: text: endpoint_id: - name: Endpoint ID - description: Endpoint id for the cluster required: true selector: number: @@ -88,16 +57,12 @@ set_zigbee_cluster_attribute: max: 65535 mode: box cluster_id: - name: Cluster ID - description: ZCL cluster to retrieve attributes for required: true selector: number: min: 1 max: 65535 cluster_type: - name: Cluster Type - description: type of the cluster default: "in" selector: select: @@ -105,8 +70,6 @@ set_zigbee_cluster_attribute: - "in" - "out" attribute: - name: Attribute - description: id of the attribute to set required: true example: 0 selector: @@ -114,50 +77,35 @@ set_zigbee_cluster_attribute: min: 1 max: 65535 value: - name: Value - description: value to write to the attribute required: true example: 0x0001 selector: text: manufacturer: - name: Manufacturer - description: manufacturer code example: 0x00FC selector: text: issue_zigbee_cluster_command: - name: Issue zigbee cluster command - description: >- - Issue command on the specified cluster on the specified entity. fields: ieee: - name: IEEE - description: IEEE address for the device required: true example: "00:0d:6f:00:05:7d:2d:34" selector: text: endpoint_id: - name: Endpoint ID - description: Endpoint id for the cluster required: true selector: number: min: 1 max: 65535 cluster_id: - name: Cluster ID - description: ZCL cluster to retrieve attributes for required: true selector: number: min: 1 max: 65535 cluster_type: - name: Cluster Type - description: type of the cluster default: "in" selector: select: @@ -165,16 +113,12 @@ issue_zigbee_cluster_command: - "in" - "out" command: - name: Command - description: id of the command to execute required: true selector: number: min: 1 max: 65535 command_type: - name: Command Type - description: type of the command to execute required: true selector: select: @@ -182,46 +126,31 @@ issue_zigbee_cluster_command: - "client" - "server" args: - name: Args - description: args to pass to the command example: "[arg1, arg2, argN]" selector: object: params: - name: Params - description: parameters to pass to the command selector: object: manufacturer: - name: Manufacturer - description: manufacturer code example: 0x00FC selector: text: issue_zigbee_group_command: - name: Issue zigbee group command - description: >- - Issue command on the specified cluster on the specified group. fields: group: - name: Group - description: Hexadecimal address of the group required: true example: 0x0222 selector: text: cluster_id: - name: Cluster ID - description: ZCL cluster to send command to required: true selector: number: min: 1 max: 65535 cluster_type: - name: Cluster Type - description: type of the cluster default: "in" selector: select: @@ -229,42 +158,28 @@ issue_zigbee_group_command: - "in" - "out" command: - name: Command - description: id of the command to execute required: true selector: number: min: 1 max: 65535 args: - name: Args - description: args to pass to the command example: "[arg1, arg2, argN]" selector: object: manufacturer: - name: Manufacturer - description: manufacturer code example: 0x00FC selector: text: warning_device_squawk: - name: Warning device squawk - description: >- - This service uses the WD capabilities to emit a quick audible/visible pulse called a "squawk". The squawk command has no effect if the WD is currently active (warning in progress). fields: ieee: - name: IEEE - description: IEEE address for the device required: true example: "00:0d:6f:00:05:7d:2d:34" selector: text: mode: - name: Mode - description: >- - The Squawk Mode field is used as a 4-bit enumeration, and can have one of the values shown in Table 8-24 of the ZCL spec - Squawk Mode Field. The exact operation of each mode (how the WD “squawks”) is implementation specific. default: 0 selector: number: @@ -272,9 +187,6 @@ warning_device_squawk: max: 1 mode: box strobe: - name: Strobe - description: >- - The strobe field is used as a Boolean, and determines if the visual indication is also required in addition to the audible squawk, as shown in Table 8-25 of the ZCL spec - Strobe Bit. default: 1 selector: number: @@ -282,9 +194,6 @@ warning_device_squawk: max: 1 mode: box level: - name: Level - description: >- - The squawk level field is used as a 2-bit enumeration, and determines the intensity of audible squawk sound as shown in Table 8-26 of the ZCL spec - Squawk Level Field Values. default: 2 selector: number: @@ -293,21 +202,13 @@ warning_device_squawk: mode: box warning_device_warn: - name: Warning device warn - description: >- - This service starts the WD operation. The WD alerts the surrounding area by audible (siren) and visual (strobe) signals. fields: ieee: - name: IEEE - description: IEEE address for the device required: true example: "00:0d:6f:00:05:7d:2d:34" selector: text: mode: - name: Mode - description: >- - The Warning Mode field is used as an 4-bit enumeration, can have one of the values 0-6 defined below in table 8-20 of the ZCL spec. The exact behavior of the WD device in each mode is according to the relevant security standards. default: 3 selector: number: @@ -315,9 +216,6 @@ warning_device_warn: max: 6 mode: box strobe: - name: Strobe - description: >- - The Strobe field is used as a 2-bit enumeration, and determines if the visual indication is required in addition to the audible siren, as indicated in Table 8-21 of the ZCL spec. "0" means no strobe, "1" means strobe. If the strobe field is “1” and the Warning Mode is “0” (“Stop”) then only the strobe is activated. default: 1 selector: number: @@ -325,9 +223,6 @@ warning_device_warn: max: 1 mode: box level: - name: Level - description: >- - The Siren Level field is used as a 2-bit enumeration, and indicates the intensity of audible squawk sound as shown in Table 8-22 of the ZCL spec. default: 2 selector: number: @@ -335,9 +230,6 @@ warning_device_warn: max: 3 mode: box duration: - name: Duration - description: >- - Requested duration of warning, in seconds (16 bit). If both Strobe and Warning Mode are "0" this field SHALL be ignored. default: 5 selector: number: @@ -345,9 +237,6 @@ warning_device_warn: max: 65535 unit_of_measurement: seconds duty_cycle: - name: Duty cycle - description: >- - Indicates the length of the flash cycle. This provides a means of varying the flash duration for different alarm types (e.g., fire, police, burglar). Valid range is 0-100 in increments of 10. All other values SHALL be rounded to the nearest valid value. Strobe SHALL calculate duty cycle over a duration of one second. The ON state SHALL precede the OFF state. For example, if Strobe Duty Cycle Field specifies “40,” then the strobe SHALL flash ON for 4/10ths of a second and then turn OFF for 6/10ths of a second. default: 0 selector: number: @@ -355,9 +244,6 @@ warning_device_warn: max: 100 step: 10 intensity: - name: Intensity - description: >- - Indicates the intensity of the strobe as shown in Table 8-23 of the ZCL spec. This attribute is designed to vary the output of the strobe (i.e., brightness) and not its frequency, which is detailed in section 8.4.2.3.1.6 of the ZCL spec. default: 2 selector: number: @@ -366,71 +252,53 @@ warning_device_warn: mode: box clear_lock_user_code: - name: Clear lock user - description: Clear a user code from a lock target: entity: domain: lock integration: zha fields: code_slot: - name: Code slot - description: Code slot to clear code from required: true example: 1 selector: text: enable_lock_user_code: - name: Enable lock user - description: Enable a user code on a lock target: entity: domain: lock integration: zha fields: code_slot: - name: Code slot - description: Code slot to enable required: true example: 1 selector: text: disable_lock_user_code: - name: Disable lock user - description: Disable a user code on a lock target: entity: domain: lock integration: zha fields: code_slot: - name: Code slot - description: Code slot to disable required: true example: 1 selector: text: set_lock_user_code: - name: Set lock user code - description: Set a user code on a lock target: entity: domain: lock integration: zha fields: code_slot: - name: Code slot - description: Code slot to set the code in required: true example: 1 selector: text: user_code: - name: Code - description: Code to set required: true example: 1234 selector: diff --git a/homeassistant/components/zha/strings.json b/homeassistant/components/zha/strings.json index cbdc9cf8477c3f..efc71df7adc5f0 100644 --- a/homeassistant/components/zha/strings.json +++ b/homeassistant/components/zha/strings.json @@ -4,7 +4,9 @@ "step": { "choose_serial_port": { "title": "Select a Serial Port", - "data": { "path": "Serial Device Path" }, + "data": { + "path": "Serial Device Path" + }, "description": "Select the serial port for your Zigbee radio" }, "confirm": { @@ -14,7 +16,9 @@ "description": "Do you want to set up {name}?" }, "manual_pick_radio_type": { - "data": { "radio_type": "Radio Type" }, + "data": { + "radio_type": "Radio Type" + }, "title": "Radio Type", "description": "Pick your Zigbee radio type" }, @@ -244,5 +248,259 @@ "face_5": "With face 5 activated", "face_6": "With face 6 activated" } + }, + "services": { + "permit": { + "name": "Permit", + "description": "Allows nodes to join the Zigbee network.", + "fields": { + "duration": { + "name": "Duration", + "description": "Time to permit joins." + }, + "ieee": { + "name": "IEEE", + "description": "IEEE address of the node permitting new joins." + }, + "source_ieee": { + "name": "Source IEEE", + "description": "IEEE address of the joining device (must be used with the install code)." + }, + "install_code": { + "name": "Install code", + "description": "Install code of the joining device (must be used with the source_ieee)." + }, + "qr_code": { + "name": "QR code", + "description": "Value of the QR install code (different between vendors)." + } + } + }, + "remove": { + "name": "Remove", + "description": "Removes a node from the Zigbee network.", + "fields": { + "ieee": { + "name": "[%key:component::zha::services::permit::fields::ieee::name%]", + "description": "IEEE address of the node to remove." + } + } + }, + "reconfigure_device": { + "name": "Reconfigure device", + "description": "Reconfigures a ZHA device (heal device). Use this if you are having issues with the device. If the device in question is a battery-powered device, ensure it is awake and accepting commands when you use this service.", + "fields": { + "ieee": { + "name": "[%key:component::zha::services::permit::fields::ieee::name%]", + "description": "IEEE address of the device to reconfigure." + } + } + }, + "set_zigbee_cluster_attribute": { + "name": "Set zigbee cluster attribute", + "description": "Sets an attribute value for the specified cluster on the specified entity.", + "fields": { + "ieee": { + "name": "[%key:component::zha::services::permit::fields::ieee::name%]", + "description": "IEEE address for the device." + }, + "endpoint_id": { + "name": "Endpoint ID", + "description": "Endpoint ID for the cluster." + }, + "cluster_id": { + "name": "Cluster ID", + "description": "ZCL cluster to retrieve attributes for." + }, + "cluster_type": { + "name": "Cluster Type", + "description": "Type of the cluster." + }, + "attribute": { + "name": "Attribute", + "description": "ID of the attribute to set." + }, + "value": { + "name": "Value", + "description": "Value to write to the attribute." + }, + "manufacturer": { + "name": "Manufacturer", + "description": "Manufacturer code." + } + } + }, + "issue_zigbee_cluster_command": { + "name": "Issue zigbee cluster command", + "description": "Issues a command on the specified cluster on the specified entity.", + "fields": { + "ieee": { + "name": "[%key:component::zha::services::permit::fields::ieee::name%]", + "description": "[%key:component::zha::services::set_zigbee_cluster_attribute::fields::ieee::description%]" + }, + "endpoint_id": { + "name": "[%key:component::zha::services::set_zigbee_cluster_attribute::fields::endpoint_id::name%]", + "description": "[%key:component::zha::services::set_zigbee_cluster_attribute::fields::endpoint_id::description%]" + }, + "cluster_id": { + "name": "[%key:component::zha::services::set_zigbee_cluster_attribute::fields::cluster_id::name%]", + "description": "[%key:component::zha::services::set_zigbee_cluster_attribute::fields::cluster_id::description%]" + }, + "cluster_type": { + "name": "[%key:component::zha::services::set_zigbee_cluster_attribute::fields::cluster_type::name%]", + "description": "[%key:component::zha::services::set_zigbee_cluster_attribute::fields::cluster_type::description%]" + }, + "command": { + "name": "Command", + "description": "ID of the command to execute." + }, + "command_type": { + "name": "Command Type", + "description": "Type of the command to execute." + }, + "args": { + "name": "Args", + "description": "Arguments to pass to the command." + }, + "params": { + "name": "Params", + "description": "Parameters to pass to the command." + }, + "manufacturer": { + "name": "Manufacturer", + "description": "Manufacturer code." + } + } + }, + "issue_zigbee_group_command": { + "name": "Issue zigbee group command", + "description": "Issue command on the specified cluster on the specified group.", + "fields": { + "group": { + "name": "Group", + "description": "Hexadecimal address of the group." + }, + "cluster_id": { + "name": "Cluster ID", + "description": "ZCL cluster to send command to." + }, + "cluster_type": { + "name": "Cluster type", + "description": "Type of the cluster." + }, + "command": { + "name": "Command", + "description": "ID of the command to execute." + }, + "args": { + "name": "Args", + "description": "Arguments to pass to the command." + }, + "manufacturer": { + "name": "Manufacturer", + "description": "Manufacturer code." + } + } + }, + "warning_device_squawk": { + "name": "Warning device squawk", + "description": "This service uses the WD capabilities to emit a quick audible/visible pulse called a \"squawk\". The squawk command has no effect if the WD is currently active (warning in progress).", + "fields": { + "ieee": { + "name": "[%key:component::zha::services::permit::fields::ieee::name%]", + "description": "IEEE address for the device." + }, + "mode": { + "name": "Mode", + "description": "The Squawk Mode field is used as a 4-bit enumeration, and can have one of the values shown in Table 8-24 of the ZCL spec - Squawk Mode Field. The exact operation of each mode (how the WD \u201csquawks\u201d) is implementation specific." + }, + "strobe": { + "name": "Strobe", + "description": "The strobe field is used as a Boolean, and determines if the visual indication is also required in addition to the audible squawk, as shown in Table 8-25 of the ZCL spec - Strobe Bit." + }, + "level": { + "name": "Level", + "description": "The squawk level field is used as a 2-bit enumeration, and determines the intensity of audible squawk sound as shown in Table 8-26 of the ZCL spec - Squawk Level Field Values." + } + } + }, + "warning_device_warn": { + "name": "Warning device warn", + "description": "This service starts the WD operation. The WD alerts the surrounding area by audible (siren) and visual (strobe) signals.", + "fields": { + "ieee": { + "name": "[%key:component::zha::services::permit::fields::ieee::name%]", + "description": "IEEE address for the device." + }, + "mode": { + "name": "Mode", + "description": "The Warning Mode field is used as an 4-bit enumeration, can have one of the values 0-6 defined below in table 8-20 of the ZCL spec. The exact behavior of the WD device in each mode is according to the relevant security standards." + }, + "strobe": { + "name": "Strobe", + "description": "The Strobe field is used as a 2-bit enumeration, and determines if the visual indication is required in addition to the audible siren, as indicated in Table 8-21 of the ZCL spec. \"0\" means no strobe, \"1\" means strobe. If the strobe field is \u201c1\u201d and the Warning Mode is \u201c0\u201d (\u201cStop\u201d) then only the strobe is activated." + }, + "level": { + "name": "Level", + "description": "The Siren Level field is used as a 2-bit enumeration, and indicates the intensity of audible squawk sound as shown in Table 8-22 of the ZCL spec." + }, + "duration": { + "name": "Duration", + "description": "Requested duration of warning, in seconds (16 bit). If both Strobe and Warning Mode are \"0\" this field SHALL be ignored." + }, + "duty_cycle": { + "name": "Duty cycle", + "description": "Indicates the length of the flash cycle. This allows you to vary the flash duration for different alarm types (e.g., fire, police, burglar). The valid range is 0-100 in increments of 10. All other values must be rounded to the nearest valid value. Strobe calculates a duty cycle over a duration of one second. The ON state must precede the OFF state. For example, if Strobe Duty Cycle Field specifies \u201c40,\u201d, then the strobe flashes ON for 4/10ths of a second and then turns OFF for 6/10ths of a second." + }, + "intensity": { + "name": "Intensity", + "description": "Indicates the intensity of the strobe as shown in Table 8-23 of the ZCL spec. This attribute is designed to vary the output of the strobe (i.e., brightness) and not its frequency, which is detailed in section 8.4.2.3.1.6 of the ZCL spec." + } + } + }, + "clear_lock_user_code": { + "name": "Clear lock user", + "description": "Clears a user code from a lock.", + "fields": { + "code_slot": { + "name": "Code slot", + "description": "Code slot to clear code from." + } + } + }, + "enable_lock_user_code": { + "name": "Enable lock user", + "description": "Enables a user code on a lock.", + "fields": { + "code_slot": { + "name": "[%key:component::zha::services::clear_lock_user_code::fields::code_slot::name%]", + "description": "Code slot to enable." + } + } + }, + "disable_lock_user_code": { + "name": "Disable lock user", + "description": "Disables a user code on a lock.", + "fields": { + "code_slot": { + "name": "[%key:component::zha::services::clear_lock_user_code::fields::code_slot::name%]", + "description": "Code slot to disable." + } + } + }, + "set_lock_user_code": { + "name": "Set lock user code", + "description": "Sets a user code on a lock.", + "fields": { + "code_slot": { + "name": "[%key:component::zha::services::clear_lock_user_code::fields::code_slot::name%]", + "description": "Code slot to set the code in." + }, + "user_code": { + "name": "Code", + "description": "Code to set." + } + } + } } } From 400c513209470889ee1d9a5525393bce27fbd2b3 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Wed, 12 Jul 2023 20:54:48 +0200 Subject: [PATCH 117/154] Always add guest wifi qr code entity in AVM Fritz!Tools (#96435) --- homeassistant/components/fritz/image.py | 3 -- .../fritz/snapshots/test_image.ambr | 3 ++ tests/components/fritz/test_image.py | 44 +++++++++---------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/homeassistant/components/fritz/image.py b/homeassistant/components/fritz/image.py index 597dd8ddb5390f..d14c562bd7652b 100644 --- a/homeassistant/components/fritz/image.py +++ b/homeassistant/components/fritz/image.py @@ -30,9 +30,6 @@ async def async_setup_entry( avm_wrapper.fritz_guest_wifi.get_info ) - if not guest_wifi_info.get("NewEnable"): - return - async_add_entities( [ FritzGuestWifiQRImage( diff --git a/tests/components/fritz/snapshots/test_image.ambr b/tests/components/fritz/snapshots/test_image.ambr index b64d8601a8aa42..452aab2a887230 100644 --- a/tests/components/fritz/snapshots/test_image.ambr +++ b/tests/components/fritz/snapshots/test_image.ambr @@ -8,6 +8,9 @@ # name: test_image_entity[fc_data0] b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x94\x00\x00\x00\x94\x01\x00\x00\x00\x00]G=y\x00\x00\x00\xf5IDATx\xda\xedVQ\x0eC!\x0c"\xbb@\xef\x7fKn\xe0\x00\xfd\xdb\xcf6\xf9|\xc6\xc4\xc6\x0f\xd2\x02\xadb},\xe2\xb9\xfb\xe5\x0e\xc0(\x18\xf2\x84/|\xaeo\xef\x847\xda\x14\x1af\x1c\xde\xe3\x19(X\tKxN\xb2\x87\x17j9\x1d None: - """Test image entities.""" - - entry = MockConfigEntry(domain=DOMAIN, data=MOCK_USER_DATA) - entry.add_to_hass(hass) - - assert await async_setup_component(hass, DOMAIN, {}) - await hass.async_block_till_done() - assert entry.state == ConfigEntryState.LOADED - - images = hass.states.async_all(IMAGE_DOMAIN) - assert len(images) == 0 From 709d5241ecfbb00490ed27aa012e71bf888acbdf Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Wed, 12 Jul 2023 18:52:17 -0400 Subject: [PATCH 118/154] Include a warning when changing channels with multi-PAN (#96351) * Inform users of the dangers of changing channels with multi-PAN * Update homeassistant/components/homeassistant_hardware/strings.json Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> * Remove double spaces --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --- homeassistant/components/homeassistant_hardware/strings.json | 3 ++- .../components/homeassistant_sky_connect/strings.json | 3 ++- homeassistant/components/homeassistant_yellow/strings.json | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/homeassistant_hardware/strings.json b/homeassistant/components/homeassistant_hardware/strings.json index 06221fc7b97f91..45e85f5a4746ed 100644 --- a/homeassistant/components/homeassistant_hardware/strings.json +++ b/homeassistant/components/homeassistant_hardware/strings.json @@ -22,7 +22,8 @@ "title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::reconfigure_addon::title%]", "data": { "channel": "Channel" - } + }, + "description": "Start a channel change for your Zigbee and Thread networks.\n\nNote: this is an advanced operation and can leave your Thread and Zigbee networks inoperable if the new channel is congested. Depending on existing network conditions, many of your devices may not migrate to the new channel and will require re-joining before they start working again. Use with caution.\n\nOnce you selected **Submit**, the channel change starts quietly in the background and will finish after a few minutes. " }, "install_addon": { "title": "The Silicon Labs Multiprotocol add-on installation has started" diff --git a/homeassistant/components/homeassistant_sky_connect/strings.json b/homeassistant/components/homeassistant_sky_connect/strings.json index 047130e787cac1..9bc1a49125b8fc 100644 --- a/homeassistant/components/homeassistant_sky_connect/strings.json +++ b/homeassistant/components/homeassistant_sky_connect/strings.json @@ -21,7 +21,8 @@ "title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::change_channel::title%]", "data": { "channel": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::change_channel::data::channel%]" - } + }, + "description": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::change_channel::description%]" }, "install_addon": { "title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::install_addon::title%]" diff --git a/homeassistant/components/homeassistant_yellow/strings.json b/homeassistant/components/homeassistant_yellow/strings.json index 617e61336a5ef1..644a3c045531c8 100644 --- a/homeassistant/components/homeassistant_yellow/strings.json +++ b/homeassistant/components/homeassistant_yellow/strings.json @@ -21,7 +21,8 @@ "title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::change_channel::title%]", "data": { "channel": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::change_channel::data::channel%]" - } + }, + "description": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::change_channel::description%]" }, "hardware_settings": { "title": "Configure hardware settings", From 70096832267ea523f990cd18fa3f4aef8ee2dace Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 12 Jul 2023 14:37:28 -1000 Subject: [PATCH 119/154] Ensure ESPHome dashboard connection recovers if its down when core starts (#96449) --- homeassistant/components/esphome/dashboard.py | 7 ------- tests/components/esphome/test_dashboard.py | 4 +++- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/esphome/dashboard.py b/homeassistant/components/esphome/dashboard.py index c9d74f0b30c62a..4cbb9cbe847281 100644 --- a/homeassistant/components/esphome/dashboard.py +++ b/homeassistant/components/esphome/dashboard.py @@ -93,13 +93,6 @@ async def async_set_dashboard_info( hass, addon_slug, url, async_get_clientsession(hass) ) await dashboard.async_request_refresh() - if not cur_dashboard and not dashboard.last_update_success: - # If there was no previous dashboard and the new one is not available, - # we skip setup and wait for discovery. - _LOGGER.error( - "Dashboard unavailable; skipping setup: %s", dashboard.last_exception - ) - return self._current_dashboard = dashboard diff --git a/tests/components/esphome/test_dashboard.py b/tests/components/esphome/test_dashboard.py index d16bf7c4d0073d..d8732ea0453f0b 100644 --- a/tests/components/esphome/test_dashboard.py +++ b/tests/components/esphome/test_dashboard.py @@ -58,7 +58,9 @@ async def test_setup_dashboard_fails( assert mock_config_entry.state == ConfigEntryState.LOADED assert mock_get_devices.call_count == 1 - assert dashboard.STORAGE_KEY not in hass_storage + # The dashboard addon might recover later so we still + # allow it to be set up. + assert dashboard.STORAGE_KEY in hass_storage async def test_setup_dashboard_fails_when_already_setup( From 08af42b00ee3d9b2593a8afda53da7ababd1d76c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 12 Jul 2023 14:39:51 -1000 Subject: [PATCH 120/154] Fix mixed case service schema registration (#96448) --- homeassistant/core.py | 2 +- homeassistant/helpers/service.py | 3 +++ tests/helpers/test_service.py | 21 +++++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/homeassistant/core.py b/homeassistant/core.py index 82ea72281570d0..54f44d0998c546 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -1770,7 +1770,7 @@ def supports_response(self, domain: str, service: str) -> SupportsResponse: the context. Will return NONE if the service does not exist as there is other error handling when calling the service if it does not exist. """ - if not (handler := self._services[domain][service]): + if not (handler := self._services[domain.lower()][service.lower()]): return SupportsResponse.NONE return handler.supports_response diff --git a/homeassistant/helpers/service.py b/homeassistant/helpers/service.py index ab0b4ea32e9610..16a79b3ae12b60 100644 --- a/homeassistant/helpers/service.py +++ b/homeassistant/helpers/service.py @@ -701,6 +701,9 @@ def async_set_service_schema( hass: HomeAssistant, domain: str, service: str, schema: dict[str, Any] ) -> None: """Register a description for a service.""" + domain = domain.lower() + service = service.lower() + descriptions_cache: dict[ tuple[str, str], dict[str, Any] | None ] = hass.data.setdefault(SERVICE_DESCRIPTION_CACHE, {}) diff --git a/tests/helpers/test_service.py b/tests/helpers/test_service.py index 674d2e1af4c243..d41b55c0b482b4 100644 --- a/tests/helpers/test_service.py +++ b/tests/helpers/test_service.py @@ -762,6 +762,27 @@ async def test_async_get_all_descriptions_dynamically_created_services( } +async def test_register_with_mixed_case(hass: HomeAssistant) -> None: + """Test registering a service with mixed case. + + For backwards compatibility, we have historically allowed mixed case, + and automatically converted it to lowercase. + """ + logger = hass.components.logger + logger_config = {logger.DOMAIN: {}} + await async_setup_component(hass, logger.DOMAIN, logger_config) + logger_domain_mixed = "LoGgEr" + hass.services.async_register( + logger_domain_mixed, "NeW_SeRVICE", lambda x: None, None + ) + service.async_set_service_schema( + hass, logger_domain_mixed, "NeW_SeRVICE", {"description": "new service"} + ) + descriptions = await service.async_get_all_descriptions(hass) + assert "description" in descriptions[logger.DOMAIN]["new_service"] + assert descriptions[logger.DOMAIN]["new_service"]["description"] == "new service" + + async def test_call_with_required_features(hass: HomeAssistant, mock_entities) -> None: """Test service calls invoked only if entity has required features.""" test_service_mock = AsyncMock(return_value=None) From b367c95c8179dfb02890c782b82bd64414599200 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Thu, 13 Jul 2023 04:00:05 +0200 Subject: [PATCH 121/154] Add more common translations (#96429) * Add common translations * Add common translations * Add common translations * Add common translations * Add common translations * Add common translations * Add common translations * Add common translations --- .../components/advantage_air/strings.json | 2 +- homeassistant/components/alert/strings.json | 6 ++--- .../components/automation/strings.json | 8 +++--- .../components/bayesian/strings.json | 2 +- homeassistant/components/bond/strings.json | 2 +- homeassistant/components/button/strings.json | 2 +- homeassistant/components/camera/strings.json | 8 +++--- homeassistant/components/climate/strings.json | 4 +-- .../components/color_extractor/strings.json | 2 +- .../components/command_line/strings.json | 2 +- homeassistant/components/cover/strings.json | 8 +++--- homeassistant/components/debugpy/strings.json | 2 +- homeassistant/components/deconz/strings.json | 8 +++--- homeassistant/components/fan/strings.json | 6 ++--- homeassistant/components/ffmpeg/strings.json | 6 ++--- homeassistant/components/filter/strings.json | 2 +- homeassistant/components/generic/strings.json | 2 +- .../generic_thermostat/strings.json | 2 +- .../components/google_mail/strings.json | 2 +- homeassistant/components/group/strings.json | 2 +- homeassistant/components/hassio/strings.json | 2 +- .../components/history_stats/strings.json | 2 +- .../components/homeassistant/strings.json | 4 +-- homeassistant/components/homekit/strings.json | 2 +- homeassistant/components/hue/strings.json | 4 +-- .../components/humidifier/strings.json | 6 ++--- .../components/input_boolean/strings.json | 8 +++--- .../components/input_datetime/strings.json | 2 +- .../components/input_number/strings.json | 2 +- .../components/input_select/strings.json | 2 +- .../components/input_text/strings.json | 2 +- homeassistant/components/insteon/strings.json | 2 +- .../components/intent_script/strings.json | 2 +- homeassistant/components/keba/strings.json | 4 +-- homeassistant/components/knx/strings.json | 2 +- homeassistant/components/lifx/strings.json | 2 +- homeassistant/components/light/strings.json | 6 ++--- .../components/litterrobot/strings.json | 2 +- homeassistant/components/lock/strings.json | 2 +- .../components/media_player/strings.json | 10 +++---- homeassistant/components/min_max/strings.json | 2 +- homeassistant/components/modbus/strings.json | 6 ++--- homeassistant/components/mqtt/strings.json | 6 ++--- homeassistant/components/nuki/strings.json | 2 +- homeassistant/components/nzbget/strings.json | 2 +- homeassistant/components/person/strings.json | 2 +- homeassistant/components/pi_hole/strings.json | 2 +- homeassistant/components/ping/strings.json | 2 +- .../components/profiler/strings.json | 2 +- .../components/python_script/strings.json | 2 +- .../components/recorder/strings.json | 4 +-- homeassistant/components/remote/strings.json | 6 ++--- homeassistant/components/rest/strings.json | 2 +- homeassistant/components/sabnzbd/strings.json | 2 +- homeassistant/components/scene/strings.json | 2 +- .../components/schedule/strings.json | 2 +- homeassistant/components/script/strings.json | 8 +++--- homeassistant/components/siren/strings.json | 6 ++--- homeassistant/components/smtp/strings.json | 2 +- .../components/snapcast/strings.json | 2 +- .../components/statistics/strings.json | 2 +- homeassistant/components/switch/strings.json | 6 ++--- .../components/telegram/strings.json | 2 +- .../components/template/strings.json | 2 +- homeassistant/components/timer/strings.json | 4 +-- .../trafikverket_ferry/strings.json | 14 +++++----- .../trafikverket_train/strings.json | 14 +++++----- homeassistant/components/trend/strings.json | 2 +- .../components/universal/strings.json | 2 +- homeassistant/components/vacuum/strings.json | 10 +++---- .../components/wolflink/strings.json | 6 ++--- homeassistant/components/workday/strings.json | 14 +++++----- homeassistant/components/yamaha/strings.json | 2 +- homeassistant/components/zha/strings.json | 8 +++--- homeassistant/components/zone/strings.json | 2 +- homeassistant/strings.json | 27 +++++++++++++++++++ 76 files changed, 177 insertions(+), 150 deletions(-) diff --git a/homeassistant/components/advantage_air/strings.json b/homeassistant/components/advantage_air/strings.json index 39681201766a2f..de8bde6897e60f 100644 --- a/homeassistant/components/advantage_air/strings.json +++ b/homeassistant/components/advantage_air/strings.json @@ -13,7 +13,7 @@ "port": "[%key:common::config_flow::data::port%]" }, "description": "Connect to the API of your Advantage Air wall mounted tablet.", - "title": "Connect" + "title": "[%key:common::action::connect%]" } } }, diff --git a/homeassistant/components/alert/strings.json b/homeassistant/components/alert/strings.json index 16192d5d59561d..f8c1b2ede72eb9 100644 --- a/homeassistant/components/alert/strings.json +++ b/homeassistant/components/alert/strings.json @@ -12,15 +12,15 @@ }, "services": { "toggle": { - "name": "Toggle", + "name": "[%key:common::action::toggle%]", "description": "Toggles alert's notifications." }, "turn_off": { - "name": "Turn off", + "name": "[%key:common::action::turn_off%]", "description": "Silences alert's notifications." }, "turn_on": { - "name": "Turn on", + "name": "[%key:common::action::turn_on%]", "description": "Resets alert's notifications." } } diff --git a/homeassistant/components/automation/strings.json b/homeassistant/components/automation/strings.json index cfeafa856d2e14..31bd812a947430 100644 --- a/homeassistant/components/automation/strings.json +++ b/homeassistant/components/automation/strings.json @@ -47,11 +47,11 @@ }, "services": { "turn_on": { - "name": "Turn on", + "name": "[%key:common::action::turn_on%]", "description": "Enables an automation." }, "turn_off": { - "name": "Turn off", + "name": "[%key:common::action::turn_off%]", "description": "Disables an automation.", "fields": { "stop_actions": { @@ -61,7 +61,7 @@ } }, "toggle": { - "name": "Toggle", + "name": "[%key:common::action::toggle%]", "description": "Toggles (enable / disable) an automation." }, "trigger": { @@ -75,7 +75,7 @@ } }, "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads the automation configuration." } } diff --git a/homeassistant/components/bayesian/strings.json b/homeassistant/components/bayesian/strings.json index f7c12523b2c8c5..9ebccedc88d77c 100644 --- a/homeassistant/components/bayesian/strings.json +++ b/homeassistant/components/bayesian/strings.json @@ -11,7 +11,7 @@ }, "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads bayesian sensors from the YAML-configuration." } } diff --git a/homeassistant/components/bond/strings.json b/homeassistant/components/bond/strings.json index 9cbd895683c563..04be198d149683 100644 --- a/homeassistant/components/bond/strings.json +++ b/homeassistant/components/bond/strings.json @@ -91,7 +91,7 @@ "description": "Start decreasing the brightness of the light. (deprecated)." }, "stop": { - "name": "Stop", + "name": "[%key:common::action::stop%]", "description": "Stop any in-progress action and empty the queue. (deprecated)." } } diff --git a/homeassistant/components/button/strings.json b/homeassistant/components/button/strings.json index 39456cdf42757a..f552e9ae12b576 100644 --- a/homeassistant/components/button/strings.json +++ b/homeassistant/components/button/strings.json @@ -16,7 +16,7 @@ "name": "Identify" }, "restart": { - "name": "Restart" + "name": "[%key:common::action::restart%]" }, "update": { "name": "Update" diff --git a/homeassistant/components/camera/strings.json b/homeassistant/components/camera/strings.json index ac061194d5cc49..90b053ec0877d4 100644 --- a/homeassistant/components/camera/strings.json +++ b/homeassistant/components/camera/strings.json @@ -25,8 +25,8 @@ "motion_detection": { "name": "Motion detection", "state": { - "true": "Enabled", - "false": "Disabled" + "true": "[%key:common::state::enabled%]", + "false": "[%key:common::state::disabled%]" } }, "model_name": { @@ -37,11 +37,11 @@ }, "services": { "turn_off": { - "name": "Turn off", + "name": "[%key:common::action::turn_off%]", "description": "Turns off the camera." }, "turn_on": { - "name": "Turn on", + "name": "[%key:common::action::turn_on%]", "description": "Turns on the camera." }, "enable_motion_detection": { diff --git a/homeassistant/components/climate/strings.json b/homeassistant/components/climate/strings.json index bfe0f490cda653..c517bfd7a20b06 100644 --- a/homeassistant/components/climate/strings.json +++ b/homeassistant/components/climate/strings.json @@ -213,11 +213,11 @@ } }, "turn_on": { - "name": "Turn on", + "name": "[%key:common::action::turn_on%]", "description": "Turns climate device on." }, "turn_off": { - "name": "Turn off", + "name": "[%key:common::action::turn_off%]", "description": "Turns climate device off." } }, diff --git a/homeassistant/components/color_extractor/strings.json b/homeassistant/components/color_extractor/strings.json index df720586631552..f56a4e514b7af7 100644 --- a/homeassistant/components/color_extractor/strings.json +++ b/homeassistant/components/color_extractor/strings.json @@ -1,7 +1,7 @@ { "services": { "turn_on": { - "name": "Turn on", + "name": "[%key:common::action::turn_on%]", "description": "Sets the light RGB to the predominant color found in the image provided by URL or file path.", "fields": { "color_extract_url": { diff --git a/homeassistant/components/command_line/strings.json b/homeassistant/components/command_line/strings.json index e249ad877d56e1..9fc0de2ab28908 100644 --- a/homeassistant/components/command_line/strings.json +++ b/homeassistant/components/command_line/strings.json @@ -7,7 +7,7 @@ }, "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads command line configuration from the YAML-configuration." } } diff --git a/homeassistant/components/cover/strings.json b/homeassistant/components/cover/strings.json index 5ed02a84e0df7d..979835fcfd27f1 100644 --- a/homeassistant/components/cover/strings.json +++ b/homeassistant/components/cover/strings.json @@ -79,15 +79,15 @@ }, "services": { "open_cover": { - "name": "Open", + "name": "[%key:common::action::open%]", "description": "Opens a cover." }, "close_cover": { - "name": "Close", + "name": "[%key:common::action::close%]", "description": "Closes a cover." }, "toggle": { - "name": "Toggle", + "name": "[%key:common::action::toggle%]", "description": "Toggles a cover open/closed." }, "set_cover_position": { @@ -101,7 +101,7 @@ } }, "stop_cover": { - "name": "Stop", + "name": "[%key:common::action::stop%]", "description": "Stops the cover movement." }, "open_cover_tilt": { diff --git a/homeassistant/components/debugpy/strings.json b/homeassistant/components/debugpy/strings.json index b03a57a51dcf20..74334a15f4a5f9 100644 --- a/homeassistant/components/debugpy/strings.json +++ b/homeassistant/components/debugpy/strings.json @@ -1,7 +1,7 @@ { "services": { "start": { - "name": "Start", + "name": "[%key:common::action::stop%]", "description": "Starts the Remote Python Debugger." } } diff --git a/homeassistant/components/deconz/strings.json b/homeassistant/components/deconz/strings.json index 448a221b2ca58e..632fe832aa8e55 100644 --- a/homeassistant/components/deconz/strings.json +++ b/homeassistant/components/deconz/strings.json @@ -79,14 +79,14 @@ "remote_rotate_from_side_6": "Device rotated from \"side 6\" to \"{subtype}\"" }, "trigger_subtype": { - "turn_on": "Turn on", - "turn_off": "Turn off", + "turn_on": "[%key:common::action::turn_on%]", + "turn_off": "[%key:common::action::turn_off%]", "dim_up": "Dim up", "dim_down": "Dim down", "left": "Left", "right": "Right", - "open": "Open", - "close": "Close", + "open": "[%key:common::action::open%]", + "close": "[%key:common::action::close%]", "both_buttons": "Both buttons", "top_buttons": "Top buttons", "bottom_buttons": "Bottom buttons", diff --git a/homeassistant/components/fan/strings.json b/homeassistant/components/fan/strings.json index d3a06edbee1b23..674dcc2b92ef90 100644 --- a/homeassistant/components/fan/strings.json +++ b/homeassistant/components/fan/strings.json @@ -75,7 +75,7 @@ } }, "turn_on": { - "name": "Turn on", + "name": "[%key:common::action::turn_on%]", "description": "Turns fan on.", "fields": { "percentage": { @@ -89,7 +89,7 @@ } }, "turn_off": { - "name": "Turn off", + "name": "[%key:common::action::turn_off%]", "description": "Turns fan off." }, "oscillate": { @@ -103,7 +103,7 @@ } }, "toggle": { - "name": "Toggle", + "name": "[%key:common::action::toggle%]", "description": "Toggles the fan on/off." }, "set_direction": { diff --git a/homeassistant/components/ffmpeg/strings.json b/homeassistant/components/ffmpeg/strings.json index 9aaff2d1e9343b..66c1f19de5b285 100644 --- a/homeassistant/components/ffmpeg/strings.json +++ b/homeassistant/components/ffmpeg/strings.json @@ -1,7 +1,7 @@ { "services": { "restart": { - "name": "Restart", + "name": "[%key:common::action::restart%]", "description": "Sends a restart command to a ffmpeg based sensor.", "fields": { "entity_id": { @@ -11,7 +11,7 @@ } }, "start": { - "name": "Start", + "name": "[%key:common::action::start%]", "description": "Sends a start command to a ffmpeg based sensor.", "fields": { "entity_id": { @@ -21,7 +21,7 @@ } }, "stop": { - "name": "Stop", + "name": "[%key:common::action::stop%]", "description": "Sends a stop command to a ffmpeg based sensor.", "fields": { "entity_id": { diff --git a/homeassistant/components/filter/strings.json b/homeassistant/components/filter/strings.json index 078e5b35980def..461eed9aefa182 100644 --- a/homeassistant/components/filter/strings.json +++ b/homeassistant/components/filter/strings.json @@ -1,7 +1,7 @@ { "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads filters from the YAML-configuration." } } diff --git a/homeassistant/components/generic/strings.json b/homeassistant/components/generic/strings.json index d23bb605c7b44e..a1519fa0f48d0e 100644 --- a/homeassistant/components/generic/strings.json +++ b/homeassistant/components/generic/strings.json @@ -86,7 +86,7 @@ }, "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads generic cameras from the YAML-configuration." } } diff --git a/homeassistant/components/generic_thermostat/strings.json b/homeassistant/components/generic_thermostat/strings.json index f1525b2516da05..8834892b7abf83 100644 --- a/homeassistant/components/generic_thermostat/strings.json +++ b/homeassistant/components/generic_thermostat/strings.json @@ -1,7 +1,7 @@ { "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads generic thermostats from the YAML-configuration." } } diff --git a/homeassistant/components/google_mail/strings.json b/homeassistant/components/google_mail/strings.json index db242479783ad9..83537c6b1de3c5 100644 --- a/homeassistant/components/google_mail/strings.json +++ b/homeassistant/components/google_mail/strings.json @@ -44,7 +44,7 @@ "description": "Sets vacation responder settings for Google Mail.", "fields": { "enabled": { - "name": "Enabled", + "name": "[%key:common::state::enabled%]", "description": "Turn this off to end vacation responses." }, "title": { diff --git a/homeassistant/components/group/strings.json b/homeassistant/components/group/strings.json index 7b49eaf4186356..bbf521b06e3968 100644 --- a/homeassistant/components/group/strings.json +++ b/homeassistant/components/group/strings.json @@ -193,7 +193,7 @@ }, "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads group configuration, entities, and notify services from YAML-configuration." }, "set": { diff --git a/homeassistant/components/hassio/strings.json b/homeassistant/components/hassio/strings.json index fa8fc2d2da84d8..e954c0cccf61fe 100644 --- a/homeassistant/components/hassio/strings.json +++ b/homeassistant/components/hassio/strings.json @@ -24,7 +24,7 @@ "fix_menu": { "description": "Could not connect to `{reference}`. Check host logs for errors from the mount service for more details.\n\nUse reload to try to connect again. If you need to update `{reference}`, go to [storage]({storage_url}).", "menu_options": { - "mount_execute_reload": "Reload", + "mount_execute_reload": "[%key:common::action::reload%]", "mount_execute_remove": "Remove" } } diff --git a/homeassistant/components/history_stats/strings.json b/homeassistant/components/history_stats/strings.json index cb4601f2a096b6..ea1c94b6ec3b87 100644 --- a/homeassistant/components/history_stats/strings.json +++ b/homeassistant/components/history_stats/strings.json @@ -1,7 +1,7 @@ { "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads history stats sensors from the YAML-configuration." } } diff --git a/homeassistant/components/homeassistant/strings.json b/homeassistant/components/homeassistant/strings.json index 5a02cd196659b4..57cb5c3eb566de 100644 --- a/homeassistant/components/homeassistant/strings.json +++ b/homeassistant/components/homeassistant/strings.json @@ -56,7 +56,7 @@ "description": "Reloads the core configuration from the YAML-configuration." }, "restart": { - "name": "Restart", + "name": "[%key:common::action::restart%]", "description": "Restarts Home Assistant." }, "set_location": { @@ -74,7 +74,7 @@ } }, "stop": { - "name": "Stop", + "name": "[%key:common::action::stop%]", "description": "Stops Home Assistant." }, "toggle": { diff --git a/homeassistant/components/homekit/strings.json b/homeassistant/components/homekit/strings.json index 83177345159690..f57536263cafea 100644 --- a/homeassistant/components/homekit/strings.json +++ b/homeassistant/components/homekit/strings.json @@ -71,7 +71,7 @@ }, "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads homekit and re-process YAML-configuration." }, "reset_accessory": { diff --git a/homeassistant/components/hue/strings.json b/homeassistant/components/hue/strings.json index 54895b6e3b2435..2c3f493e2c8599 100644 --- a/homeassistant/components/hue/strings.json +++ b/homeassistant/components/hue/strings.json @@ -44,8 +44,8 @@ "double_buttons_2_4": "Second and Fourth buttons", "dim_down": "Dim down", "dim_up": "Dim up", - "turn_off": "Turn off", - "turn_on": "Turn on", + "turn_off": "[%key:common::action::turn_off%]", + "turn_on": "[%key:common::action::turn_on%]", "1": "First button", "2": "Second button", "3": "Third button", diff --git a/homeassistant/components/humidifier/strings.json b/homeassistant/components/humidifier/strings.json index d3cf946f5bf7cc..19a9a8eab77233 100644 --- a/homeassistant/components/humidifier/strings.json +++ b/homeassistant/components/humidifier/strings.json @@ -97,15 +97,15 @@ } }, "turn_on": { - "name": "Turn on", + "name": "[%key:common::action::turn_on%]", "description": "Turns the humidifier on." }, "turn_off": { - "name": "Turn off", + "name": "[%key:common::action::turn_off%]", "description": "Turns the humidifier off." }, "toggle": { - "name": "Toggle", + "name": "[%key:common::action::toggle%]", "description": "Toggles the humidifier on/off." } } diff --git a/homeassistant/components/input_boolean/strings.json b/homeassistant/components/input_boolean/strings.json index 9288de04f2c1f5..a2087f1247a579 100644 --- a/homeassistant/components/input_boolean/strings.json +++ b/homeassistant/components/input_boolean/strings.json @@ -20,19 +20,19 @@ }, "services": { "toggle": { - "name": "Toggle", + "name": "[%key:common::action::toggle%]", "description": "Toggles the helper on/off." }, "turn_off": { - "name": "Turn off", + "name": "[%key:common::action::turn_off%]", "description": "Turns off the helper." }, "turn_on": { - "name": "Turn on", + "name": "[%key:common::action::turn_on%]", "description": "Turns on the helper." }, "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads helpers from the YAML-configuration." } } diff --git a/homeassistant/components/input_datetime/strings.json b/homeassistant/components/input_datetime/strings.json index f657508a4c4688..e4a2b6349b7ef6 100644 --- a/homeassistant/components/input_datetime/strings.json +++ b/homeassistant/components/input_datetime/strings.json @@ -59,7 +59,7 @@ } }, "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads helpers from the YAML-configuration." } } diff --git a/homeassistant/components/input_number/strings.json b/homeassistant/components/input_number/strings.json index 020544c5d4eaac..8a2351ebad46b4 100644 --- a/homeassistant/components/input_number/strings.json +++ b/homeassistant/components/input_number/strings.json @@ -54,7 +54,7 @@ } }, "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads helpers from the YAML-configuration." } } diff --git a/homeassistant/components/input_select/strings.json b/homeassistant/components/input_select/strings.json index 68970933346509..faa47c979a16e8 100644 --- a/homeassistant/components/input_select/strings.json +++ b/homeassistant/components/input_select/strings.json @@ -67,7 +67,7 @@ } }, "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads helpers from the YAML-configuration." } } diff --git a/homeassistant/components/input_text/strings.json b/homeassistant/components/input_text/strings.json index a4dc6d929f5fed..49eab33848c312 100644 --- a/homeassistant/components/input_text/strings.json +++ b/homeassistant/components/input_text/strings.json @@ -42,7 +42,7 @@ } }, "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads helpers from the YAML-configuration." } } diff --git a/homeassistant/components/insteon/strings.json b/homeassistant/components/insteon/strings.json index 3f3e3df78c7bde..3ba996adff772e 100644 --- a/homeassistant/components/insteon/strings.json +++ b/homeassistant/components/insteon/strings.json @@ -144,7 +144,7 @@ "description": "Name of the device to load. Use \"all\" to load the database of all devices." }, "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads all records. If true the current records are cleared from memory (does not effect the device) and the records are reloaded. If false the existing records are left in place and only missing records are added. Default is false." } } diff --git a/homeassistant/components/intent_script/strings.json b/homeassistant/components/intent_script/strings.json index efd77d225f763b..74ddd45c1af2d4 100644 --- a/homeassistant/components/intent_script/strings.json +++ b/homeassistant/components/intent_script/strings.json @@ -1,7 +1,7 @@ { "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads the intent script from the YAML-configuration." } } diff --git a/homeassistant/components/keba/strings.json b/homeassistant/components/keba/strings.json index 140ab6ea9490ce..ed8594a1068919 100644 --- a/homeassistant/components/keba/strings.json +++ b/homeassistant/components/keba/strings.json @@ -33,11 +33,11 @@ } }, "enable": { - "name": "Enable", + "name": "[%key:common::action::enable%]", "description": "Starts a charging process if charging station is authorized." }, "disable": { - "name": "Disable", + "name": "[%key:common::action::disable%]", "description": "Stops the charging process if charging station is authorized." }, "set_failsafe": { diff --git a/homeassistant/components/knx/strings.json b/homeassistant/components/knx/strings.json index 9a17fed506c652..56ff9018530e3a 100644 --- a/homeassistant/components/knx/strings.json +++ b/homeassistant/components/knx/strings.json @@ -371,7 +371,7 @@ } }, "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads the KNX integration." } } diff --git a/homeassistant/components/lifx/strings.json b/homeassistant/components/lifx/strings.json index cff9b572cc6285..dfbc0b4e384519 100644 --- a/homeassistant/components/lifx/strings.json +++ b/homeassistant/components/lifx/strings.json @@ -52,7 +52,7 @@ "description": "Controls the HEV LEDs on a LIFX Clean bulb.", "fields": { "power": { - "name": "Enable", + "name": "[%key:common::action::enable%]", "description": "Start or stop a Clean cycle." }, "duration": { diff --git a/homeassistant/components/light/strings.json b/homeassistant/components/light/strings.json index a4a46d2ca94140..5398d38ca5d786 100644 --- a/homeassistant/components/light/strings.json +++ b/homeassistant/components/light/strings.json @@ -243,7 +243,7 @@ }, "services": { "turn_on": { - "name": "Turn on", + "name": "[%key:common::action::turn_on%]", "description": "Turn on one or more lights and adjust properties of the light, even when they are turned on already.", "fields": { "transition": { @@ -317,7 +317,7 @@ } }, "turn_off": { - "name": "Turn off", + "name": "[%key:common::action::turn_off%]", "description": "Turn off one or more lights.", "fields": { "transition": { @@ -331,7 +331,7 @@ } }, "toggle": { - "name": "Toggle", + "name": "[%key:common::action::toggle%]", "description": "Toggles one or more lights, from on to off, or, off to on, based on their current state.", "fields": { "transition": { diff --git a/homeassistant/components/litterrobot/strings.json b/homeassistant/components/litterrobot/strings.json index e5cd35703f3edb..fe9cc3b528ac61 100644 --- a/homeassistant/components/litterrobot/strings.json +++ b/homeassistant/components/litterrobot/strings.json @@ -144,7 +144,7 @@ "description": "Sets the sleep mode and start time.", "fields": { "enabled": { - "name": "Enabled", + "name": "[%key:common::state::enabled%]", "description": "Whether sleep mode should be enabled." }, "start_time": { diff --git a/homeassistant/components/lock/strings.json b/homeassistant/components/lock/strings.json index 9e20b0cad2bd5d..d041d6ac61aa01 100644 --- a/homeassistant/components/lock/strings.json +++ b/homeassistant/components/lock/strings.json @@ -47,7 +47,7 @@ } }, "open": { - "name": "Open", + "name": "[%key:common::action::open%]", "description": "Opens a lock.", "fields": { "code": { diff --git a/homeassistant/components/media_player/strings.json b/homeassistant/components/media_player/strings.json index 10148f99fef52c..bcf594a2675abd 100644 --- a/homeassistant/components/media_player/strings.json +++ b/homeassistant/components/media_player/strings.json @@ -162,15 +162,15 @@ }, "services": { "turn_on": { - "name": "Turn on", + "name": "[%key:common::action::turn_on%]", "description": "Turns on the power of the media player." }, "turn_off": { - "name": "Turn off", + "name": "[%key:common::action::turn_off%]", "description": "Turns off the power of the media player." }, "toggle": { - "name": "Toggle", + "name": "[%key:common::action::toggle%]", "description": "Toggles a media player on/off." }, "volume_up": { @@ -210,11 +210,11 @@ "description": "Starts playing." }, "media_pause": { - "name": "Pause", + "name": "[%key:common::action::pause%]", "description": "Pauses." }, "media_stop": { - "name": "Stop", + "name": "[%key:common::action::stop%]", "description": "Stops playing." }, "media_next_track": { diff --git a/homeassistant/components/min_max/strings.json b/homeassistant/components/min_max/strings.json index 464d01b90b4c91..ce18a4d153f014 100644 --- a/homeassistant/components/min_max/strings.json +++ b/homeassistant/components/min_max/strings.json @@ -46,7 +46,7 @@ }, "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads min/max sensors from the YAML-configuration." } } diff --git a/homeassistant/components/modbus/strings.json b/homeassistant/components/modbus/strings.json index ad07a4d7565966..c9cf755ad13416 100644 --- a/homeassistant/components/modbus/strings.json +++ b/homeassistant/components/modbus/strings.json @@ -1,7 +1,7 @@ { "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads all modbus entities." }, "write_coil": { @@ -49,7 +49,7 @@ } }, "stop": { - "name": "Stop", + "name": "[%key:common::action::stop%]", "description": "Stops modbus hub.", "fields": { "hub": { @@ -59,7 +59,7 @@ } }, "restart": { - "name": "Restart", + "name": "[%key:common::action::restart%]", "description": "Restarts modbus hub (if running stop then start).", "fields": { "hub": { diff --git a/homeassistant/components/mqtt/strings.json b/homeassistant/components/mqtt/strings.json index 61d2b40314b135..ae47b33774d655 100644 --- a/homeassistant/components/mqtt/strings.json +++ b/homeassistant/components/mqtt/strings.json @@ -70,8 +70,8 @@ "button_quintuple_press": "\"{subtype}\" quintuple clicked" }, "trigger_subtype": { - "turn_on": "Turn on", - "turn_off": "Turn off", + "turn_on": "[%key:common::action::turn_on%]", + "turn_off": "[%key:common::action::turn_off%]", "button_1": "First button", "button_2": "Second button", "button_3": "Third button", @@ -188,7 +188,7 @@ } }, "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads MQTT entities from the YAML-configuration." } } diff --git a/homeassistant/components/nuki/strings.json b/homeassistant/components/nuki/strings.json index 68ab508141b378..11c19bbee3ff2b 100644 --- a/homeassistant/components/nuki/strings.json +++ b/homeassistant/components/nuki/strings.json @@ -62,7 +62,7 @@ "description": "Enables or disables continuous mode on Nuki Opener.", "fields": { "enable": { - "name": "Enable", + "name": "[%key:common::action::enable%]", "description": "Whether to enable or disable the feature." } } diff --git a/homeassistant/components/nzbget/strings.json b/homeassistant/components/nzbget/strings.json index 5a96d2f8951cf6..7a3c438d11fcad 100644 --- a/homeassistant/components/nzbget/strings.json +++ b/homeassistant/components/nzbget/strings.json @@ -34,7 +34,7 @@ }, "services": { "pause": { - "name": "Pause", + "name": "[%key:common::action::pause%]", "description": "Pauses download queue." }, "resume": { diff --git a/homeassistant/components/person/strings.json b/homeassistant/components/person/strings.json index 10a982535f2f02..27c41df6b4e046 100644 --- a/homeassistant/components/person/strings.json +++ b/homeassistant/components/person/strings.json @@ -28,7 +28,7 @@ }, "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads persons from the YAML-configuration." } } diff --git a/homeassistant/components/pi_hole/strings.json b/homeassistant/components/pi_hole/strings.json index 1ed271931c36bf..b76b61f1903d0d 100644 --- a/homeassistant/components/pi_hole/strings.json +++ b/homeassistant/components/pi_hole/strings.json @@ -82,7 +82,7 @@ }, "services": { "disable": { - "name": "Disable", + "name": "[%key:common::action::disable%]", "description": "Disables configured Pi-hole(s) for an amount of time.", "fields": { "duration": { diff --git a/homeassistant/components/ping/strings.json b/homeassistant/components/ping/strings.json index 2bd9229b607973..5b5c5da46bc1d3 100644 --- a/homeassistant/components/ping/strings.json +++ b/homeassistant/components/ping/strings.json @@ -1,7 +1,7 @@ { "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads ping sensors from the YAML-configuration." } } diff --git a/homeassistant/components/profiler/strings.json b/homeassistant/components/profiler/strings.json index ee6f215e59bced..7b9f6789c79bc7 100644 --- a/homeassistant/components/profiler/strings.json +++ b/homeassistant/components/profiler/strings.json @@ -11,7 +11,7 @@ }, "services": { "start": { - "name": "Start", + "name": "[%key:common::action::stop%]", "description": "Starts the Profiler.", "fields": { "seconds": { diff --git a/homeassistant/components/python_script/strings.json b/homeassistant/components/python_script/strings.json index 9898a8ad8665eb..ccf1b33c767412 100644 --- a/homeassistant/components/python_script/strings.json +++ b/homeassistant/components/python_script/strings.json @@ -1,7 +1,7 @@ { "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads all available Python scripts." } } diff --git a/homeassistant/components/recorder/strings.json b/homeassistant/components/recorder/strings.json index a55f13b27c4f73..17539387a29582 100644 --- a/homeassistant/components/recorder/strings.json +++ b/homeassistant/components/recorder/strings.json @@ -52,11 +52,11 @@ } }, "disable": { - "name": "Disable", + "name": "[%key:common::action::disable%]", "description": "Stops the recording of events and state changes." }, "enable": { - "name": "Enable", + "name": "[%key:common::action::enable%]", "description": "Starts the recording of events and state changes." } } diff --git a/homeassistant/components/remote/strings.json b/homeassistant/components/remote/strings.json index 14331c5cded7b6..e3df487a57bd3f 100644 --- a/homeassistant/components/remote/strings.json +++ b/homeassistant/components/remote/strings.json @@ -27,7 +27,7 @@ }, "services": { "turn_on": { - "name": "Turn on", + "name": "[%key:common::action::turn_on%]", "description": "Sends the power on command.", "fields": { "activity": { @@ -37,11 +37,11 @@ } }, "toggle": { - "name": "Toggle", + "name": "[%key:common::action::toggle%]", "description": "Toggles a device on/off." }, "turn_off": { - "name": "Turn off", + "name": "[%key:common::action::turn_off%]", "description": "Turns the device off." }, "send_command": { diff --git a/homeassistant/components/rest/strings.json b/homeassistant/components/rest/strings.json index afbab8d8040ab5..d2b15461c9ee66 100644 --- a/homeassistant/components/rest/strings.json +++ b/homeassistant/components/rest/strings.json @@ -1,7 +1,7 @@ { "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads REST entities from the YAML-configuration." } } diff --git a/homeassistant/components/sabnzbd/strings.json b/homeassistant/components/sabnzbd/strings.json index 2989ee5d00be27..5711656ef690e0 100644 --- a/homeassistant/components/sabnzbd/strings.json +++ b/homeassistant/components/sabnzbd/strings.json @@ -16,7 +16,7 @@ }, "services": { "pause": { - "name": "Pause", + "name": "[%key:common::action::pause%]", "description": "Pauses downloads.", "fields": { "api_key": { diff --git a/homeassistant/components/scene/strings.json b/homeassistant/components/scene/strings.json index f4011860c785ca..3bfea1b09e7bcb 100644 --- a/homeassistant/components/scene/strings.json +++ b/homeassistant/components/scene/strings.json @@ -12,7 +12,7 @@ } }, "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads the scenes from the YAML-configuration." }, "apply": { diff --git a/homeassistant/components/schedule/strings.json b/homeassistant/components/schedule/strings.json index aea07cc3ff26c6..a40c5814d36f3b 100644 --- a/homeassistant/components/schedule/strings.json +++ b/homeassistant/components/schedule/strings.json @@ -23,7 +23,7 @@ }, "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads schedules from the YAML-configuration." } } diff --git a/homeassistant/components/script/strings.json b/homeassistant/components/script/strings.json index e4f1b3fcd4f4bb..f2d5997ae9d870 100644 --- a/homeassistant/components/script/strings.json +++ b/homeassistant/components/script/strings.json @@ -34,19 +34,19 @@ }, "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads all the available scripts." }, "turn_on": { - "name": "Turn on", + "name": "[%key:common::action::turn_on%]", "description": "Runs the sequence of actions defined in a script." }, "turn_off": { - "name": "Turn off", + "name": "[%key:common::action::turn_off%]", "description": "Stops a running script." }, "toggle": { - "name": "Toggle", + "name": "[%key:common::action::toggle%]", "description": "Toggle a script. Starts it, if isn't running, stops it otherwise." } } diff --git a/homeassistant/components/siren/strings.json b/homeassistant/components/siren/strings.json index 171a853f74c2fe..90725da9e8f23b 100644 --- a/homeassistant/components/siren/strings.json +++ b/homeassistant/components/siren/strings.json @@ -16,7 +16,7 @@ }, "services": { "turn_on": { - "name": "Turn on", + "name": "[%key:common::action::turn_on%]", "description": "Turns the siren on.", "fields": { "tone": { @@ -34,11 +34,11 @@ } }, "turn_off": { - "name": "Turn off", + "name": "[%key:common::action::turn_off%]", "description": "Turns the siren off." }, "toggle": { - "name": "Toggle", + "name": "[%key:common::action::toggle%]", "description": "Toggles the siren on/off." } } diff --git a/homeassistant/components/smtp/strings.json b/homeassistant/components/smtp/strings.json index 3c72a1a50d1a75..b711c2f2009433 100644 --- a/homeassistant/components/smtp/strings.json +++ b/homeassistant/components/smtp/strings.json @@ -1,7 +1,7 @@ { "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads smtp notify services." } } diff --git a/homeassistant/components/snapcast/strings.json b/homeassistant/components/snapcast/strings.json index 242bf62ab04f8a..0d51c7543f1b3d 100644 --- a/homeassistant/components/snapcast/strings.json +++ b/homeassistant/components/snapcast/strings.json @@ -7,7 +7,7 @@ "host": "[%key:common::config_flow::data::host%]", "port": "[%key:common::config_flow::data::port%]" }, - "title": "Connect" + "title": "[%key:common::action::connect%]" } }, "abort": { diff --git a/homeassistant/components/statistics/strings.json b/homeassistant/components/statistics/strings.json index 6b2a04a85df497..6d7bda36faecc5 100644 --- a/homeassistant/components/statistics/strings.json +++ b/homeassistant/components/statistics/strings.json @@ -1,7 +1,7 @@ { "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads statistics sensors from the YAML-configuration." } } diff --git a/homeassistant/components/switch/strings.json b/homeassistant/components/switch/strings.json index ae5a3165cd966e..b50709ed76f672 100644 --- a/homeassistant/components/switch/strings.json +++ b/homeassistant/components/switch/strings.json @@ -33,15 +33,15 @@ }, "services": { "turn_on": { - "name": "Turn on", + "name": "[%key:common::action::turn_on%]", "description": "Turns a switch on." }, "turn_off": { - "name": "Turn off", + "name": "[%key:common::action::turn_off%]", "description": "Turns a switch off." }, "toggle": { - "name": "Toggle", + "name": "[%key:common::action::toggle%]", "description": "Toggles a switch on/off." } } diff --git a/homeassistant/components/telegram/strings.json b/homeassistant/components/telegram/strings.json index 9e09a3904cd702..34a98f908dc236 100644 --- a/homeassistant/components/telegram/strings.json +++ b/homeassistant/components/telegram/strings.json @@ -1,7 +1,7 @@ { "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads telegram notify services." } } diff --git a/homeassistant/components/template/strings.json b/homeassistant/components/template/strings.json index 3222a0f1bdf5fc..fce7129353e50f 100644 --- a/homeassistant/components/template/strings.json +++ b/homeassistant/components/template/strings.json @@ -1,7 +1,7 @@ { "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads template entities from the YAML-configuration." } } diff --git a/homeassistant/components/timer/strings.json b/homeassistant/components/timer/strings.json index e21f0d2ca82484..c52f2627253ba3 100644 --- a/homeassistant/components/timer/strings.json +++ b/homeassistant/components/timer/strings.json @@ -32,7 +32,7 @@ }, "services": { "start": { - "name": "Start", + "name": "[%key:common::action::stop%]", "description": "Starts a timer.", "fields": { "duration": { @@ -42,7 +42,7 @@ } }, "pause": { - "name": "Pause", + "name": "[%key:common::action::pause%]", "description": "Pauses a timer." }, "cancel": { diff --git a/homeassistant/components/trafikverket_ferry/strings.json b/homeassistant/components/trafikverket_ferry/strings.json index 3d84e4480b406e..d98d60f4643965 100644 --- a/homeassistant/components/trafikverket_ferry/strings.json +++ b/homeassistant/components/trafikverket_ferry/strings.json @@ -30,13 +30,13 @@ "selector": { "weekday": { "options": { - "mon": "Monday", - "tue": "Tuesday", - "wed": "Wednesday", - "thu": "Thursday", - "fri": "Friday", - "sat": "Saturday", - "sun": "Sunday" + "mon": "[%key:common::time::monday%]", + "tue": "[%key:common::time::tuesday%]", + "wed": "[%key:common::time::wednesday%]", + "thu": "[%key:common::time::thursday%]", + "fri": "[%key:common::time::friday%]", + "sat": "[%key:common::time::saturday%]", + "sun": "[%key:common::time::sunday%]" } } }, diff --git a/homeassistant/components/trafikverket_train/strings.json b/homeassistant/components/trafikverket_train/strings.json index 6c67d881153a27..0089f6db8fc24c 100644 --- a/homeassistant/components/trafikverket_train/strings.json +++ b/homeassistant/components/trafikverket_train/strings.json @@ -32,13 +32,13 @@ "selector": { "weekday": { "options": { - "mon": "Monday", - "tue": "Tuesday", - "wed": "Wednesday", - "thu": "Thursday", - "fri": "Friday", - "sat": "Saturday", - "sun": "Sunday" + "mon": "[%key:common::time::monday%]", + "tue": "[%key:common::time::tuesday%]", + "wed": "[%key:common::time::wednesday%]", + "thu": "[%key:common::time::thursday%]", + "fri": "[%key:common::time::friday%]", + "sat": "[%key:common::time::saturday%]", + "sun": "[%key:common::time::sunday%]" } } } diff --git a/homeassistant/components/trend/strings.json b/homeassistant/components/trend/strings.json index 1715f019f272d6..6af231bb4c537b 100644 --- a/homeassistant/components/trend/strings.json +++ b/homeassistant/components/trend/strings.json @@ -1,7 +1,7 @@ { "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads trend sensors from the YAML-configuration." } } diff --git a/homeassistant/components/universal/strings.json b/homeassistant/components/universal/strings.json index b440d76ebc23ab..a265a7c204ce67 100644 --- a/homeassistant/components/universal/strings.json +++ b/homeassistant/components/universal/strings.json @@ -1,7 +1,7 @@ { "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads universal media players from the YAML-configuration." } } diff --git a/homeassistant/components/vacuum/strings.json b/homeassistant/components/vacuum/strings.json index 3bdf650ddd38d1..9822c2fa8216a5 100644 --- a/homeassistant/components/vacuum/strings.json +++ b/homeassistant/components/vacuum/strings.json @@ -37,15 +37,15 @@ }, "services": { "turn_on": { - "name": "Turn on", + "name": "[%key:common::action::turn_on%]", "description": "Starts a new cleaning task." }, "turn_off": { - "name": "Turn off", + "name": "[%key:common::action::turn_off%]", "description": "Stops the current cleaning task and returns to its dock." }, "stop": { - "name": "Stop", + "name": "[%key:common::action::stop%]", "description": "Stops the current cleaning task." }, "locate": { @@ -57,11 +57,11 @@ "description": "Starts, pauses, or resumes the cleaning task." }, "start": { - "name": "Start", + "name": "[%key:common::action::start%]", "description": "Starts or resumes the cleaning task." }, "pause": { - "name": "Pause", + "name": "[%key:common::action::pause%]", "description": "Pauses the cleaning task." }, "return_to_base": { diff --git a/homeassistant/components/wolflink/strings.json b/homeassistant/components/wolflink/strings.json index c8db962215f7bb..3de74cbbf4c782 100644 --- a/homeassistant/components/wolflink/strings.json +++ b/homeassistant/components/wolflink/strings.json @@ -28,10 +28,10 @@ "sensor": { "state": { "state": { - "ein": "Enabled", + "ein": "[%key:common::state::enabled%]", "deaktiviert": "Inactive", - "aus": "Disabled", - "standby": "Standby", + "aus": "[%key:common::state::disabled%]", + "standby": "[%key:common::state::standby%]", "auto": "Auto", "permanent": "Permanent", "initialisierung": "Initialization", diff --git a/homeassistant/components/workday/strings.json b/homeassistant/components/workday/strings.json index 6ea8348812d1ef..4aaf241536fa7c 100644 --- a/homeassistant/components/workday/strings.json +++ b/homeassistant/components/workday/strings.json @@ -73,13 +73,13 @@ }, "days": { "options": { - "mon": "Monday", - "tue": "Tuesday", - "wed": "Wednesday", - "thu": "Thursday", - "fri": "Friday", - "sat": "Saturday", - "sun": "Sunday", + "mon": "[%key:common::time::monday%]", + "tue": "[%key:common::time::tuesday%]", + "wed": "[%key:common::time::wednesday%]", + "thu": "[%key:common::time::thursday%]", + "fri": "[%key:common::time::friday%]", + "sat": "[%key:common::time::saturday%]", + "sun": "[%key:common::time::sunday%]", "holiday": "Holidays" } } diff --git a/homeassistant/components/yamaha/strings.json b/homeassistant/components/yamaha/strings.json index 0896f43b1b515e..ddfee94aa0449e 100644 --- a/homeassistant/components/yamaha/strings.json +++ b/homeassistant/components/yamaha/strings.json @@ -9,7 +9,7 @@ "description": "Name of port to enable/disable." }, "enabled": { - "name": "Enabled", + "name": "[%key:common::state::enabled%]", "description": "Indicate if port should be enabled or not." } } diff --git a/homeassistant/components/zha/strings.json b/homeassistant/components/zha/strings.json index efc71df7adc5f0..50eadfc6667f83 100644 --- a/homeassistant/components/zha/strings.json +++ b/homeassistant/components/zha/strings.json @@ -224,14 +224,14 @@ "device_offline": "Device offline" }, "trigger_subtype": { - "turn_on": "Turn on", - "turn_off": "Turn off", + "turn_on": "[%key:common::action::turn_on%]", + "turn_off": "[%key:common::action::turn_off%]", "dim_up": "Dim up", "dim_down": "Dim down", "left": "Left", "right": "Right", - "open": "Open", - "close": "Close", + "open": "[%key:common::action::open%]", + "close": "[%key:common::action::close%]", "both_buttons": "Both buttons", "button": "Button", "button_1": "First button", diff --git a/homeassistant/components/zone/strings.json b/homeassistant/components/zone/strings.json index b2f3b5efffa92e..a17059c5eab295 100644 --- a/homeassistant/components/zone/strings.json +++ b/homeassistant/components/zone/strings.json @@ -1,7 +1,7 @@ { "services": { "reload": { - "name": "Reload", + "name": "[%key:common::action::reload%]", "description": "Reloads zones from the YAML-configuration." } } diff --git a/homeassistant/strings.json b/homeassistant/strings.json index 51a5636092af3e..871e1b4ecbce1c 100644 --- a/homeassistant/strings.json +++ b/homeassistant/strings.json @@ -20,6 +20,31 @@ "turn_off": "Turn off {entity_name}" } }, + "action": { + "connect": "Connect", + "disconnect": "Disconnect", + "enable": "Enable", + "disable": "Disable", + "open": "Open", + "close": "Close", + "reload": "Reload", + "restart": "Restart", + "start": "Start", + "stop": "Stop", + "pause": "Pause", + "turn_on": "Turn on", + "turn_off": "Turn off", + "toggle": "Toggle" + }, + "time": { + "monday": "Monday", + "tuesday": "Tuesday", + "wednesday": "Wednesday", + "thursday": "Thursday", + "friday": "Friday", + "saturday": "Saturday", + "sunday": "Sunday" + }, "state": { "off": "Off", "on": "On", @@ -27,6 +52,8 @@ "no": "No", "open": "Open", "closed": "Closed", + "enabled": "Enabled", + "disabled": "Disabled", "connected": "Connected", "disconnected": "Disconnected", "locked": "Locked", From 127fbded18567f488408384399762aef774249db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Thu, 13 Jul 2023 05:04:18 +0300 Subject: [PATCH 122/154] Fix huawei_lte suspend_integration service URL description (#96450) Copy-pasto from resume_integration. --- homeassistant/components/huawei_lte/strings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/huawei_lte/strings.json b/homeassistant/components/huawei_lte/strings.json index 6f85187cfeb480..50c57e6db3ec29 100644 --- a/homeassistant/components/huawei_lte/strings.json +++ b/homeassistant/components/huawei_lte/strings.json @@ -86,7 +86,7 @@ "fields": { "url": { "name": "URL", - "description": "URL of router to resume integration for; optional when only one is configured." + "description": "URL of router to suspend integration for; optional when only one is configured." } } } From ffe81a97166c31268096682aec36f9a0791c44be Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 12 Jul 2023 16:46:29 -1000 Subject: [PATCH 123/154] Improve ESPHome update platform error reporting (#96455) --- homeassistant/components/esphome/update.py | 65 +++++---- tests/components/esphome/conftest.py | 10 +- tests/components/esphome/test_update.py | 149 +++++++++++++++++++-- 3 files changed, 180 insertions(+), 44 deletions(-) diff --git a/homeassistant/components/esphome/update.py b/homeassistant/components/esphome/update.py index 6f51b9df74415a..2ac69c3a22d849 100644 --- a/homeassistant/components/esphome/update.py +++ b/homeassistant/components/esphome/update.py @@ -14,6 +14,7 @@ ) from homeassistant.config_entries import ConfigEntry from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback +from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import device_registry as dr from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity import DeviceInfo @@ -27,6 +28,9 @@ KEY_UPDATE_LOCK = "esphome_update_lock" +_LOGGER = logging.getLogger(__name__) + + async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, @@ -109,14 +113,10 @@ def available(self) -> bool: During deep sleep the ESP will not be connectable (by design) and thus, even when unavailable, we'll show it as available. """ - return ( - super().available - and ( - self._entry_data.available - or self._entry_data.expected_disconnect - or self._device_info.has_deep_sleep - ) - and self._device_info.name in self.coordinator.data + return super().available and ( + self._entry_data.available + or self._entry_data.expected_disconnect + or self._device_info.has_deep_sleep ) @property @@ -137,33 +137,26 @@ def release_url(self) -> str | None: """URL to the full release notes of the latest version available.""" return "https://esphome.io/changelog/" + @callback + def _async_static_info_updated(self, _: list[EntityInfo]) -> None: + """Handle static info update.""" + self.async_write_ha_state() + async def async_added_to_hass(self) -> None: """Handle entity added to Home Assistant.""" await super().async_added_to_hass() - - @callback - def _static_info_updated(infos: list[EntityInfo]) -> None: - """Handle static info update.""" - self.async_write_ha_state() - self.async_on_remove( async_dispatcher_connect( self.hass, self._entry_data.signal_static_info_updated, - _static_info_updated, + self._async_static_info_updated, ) ) - - @callback - def _on_device_update() -> None: - """Handle update of device state, like availability.""" - self.async_write_ha_state() - self.async_on_remove( async_dispatcher_connect( self.hass, self._entry_data.signal_device_updated, - _on_device_update, + self.async_write_ha_state, ) ) @@ -172,16 +165,20 @@ async def async_install( ) -> None: """Install an update.""" async with self.hass.data.setdefault(KEY_UPDATE_LOCK, asyncio.Lock()): - device = self.coordinator.data.get(self._device_info.name) + coordinator = self.coordinator + api = coordinator.api + device = coordinator.data.get(self._device_info.name) assert device is not None - if not await self.coordinator.api.compile(device["configuration"]): - logging.getLogger(__name__).error( - "Error compiling %s. Try again in ESPHome dashboard for error", - device["configuration"], - ) - if not await self.coordinator.api.upload(device["configuration"], "OTA"): - logging.getLogger(__name__).error( - "Error OTA updating %s. Try again in ESPHome dashboard for error", - device["configuration"], - ) - await self.coordinator.async_request_refresh() + try: + if not await api.compile(device["configuration"]): + raise HomeAssistantError( + f"Error compiling {device['configuration']}; " + "Try again in ESPHome dashboard for more information." + ) + if not await api.upload(device["configuration"], "OTA"): + raise HomeAssistantError( + f"Error updating {device['configuration']} via OTA; " + "Try again in ESPHome dashboard for more information." + ) + finally: + await self.coordinator.async_request_refresh() diff --git a/tests/components/esphome/conftest.py b/tests/components/esphome/conftest.py index f4b3bfa3ec7c83..e809089da11a66 100644 --- a/tests/components/esphome/conftest.py +++ b/tests/components/esphome/conftest.py @@ -15,6 +15,7 @@ ReconnectLogic, UserService, ) +import async_timeout import pytest from zeroconf import Zeroconf @@ -53,6 +54,11 @@ async def load_homeassistant(hass) -> None: assert await async_setup_component(hass, "homeassistant", {}) +@pytest.fixture(autouse=True) +def mock_tts(mock_tts_cache_dir): + """Auto mock the tts cache.""" + + @pytest.fixture def mock_config_entry(hass) -> MockConfigEntry: """Return the default mocked config entry.""" @@ -248,10 +254,10 @@ async def mock_try_connect(self): "homeassistant.components.esphome.manager.ReconnectLogic", MockReconnectLogic ): assert await hass.config_entries.async_setup(entry.entry_id) - await try_connect_done.wait() + async with async_timeout.timeout(2): + await try_connect_done.wait() await hass.async_block_till_done() - return mock_device diff --git a/tests/components/esphome/test_update.py b/tests/components/esphome/test_update.py index 53ae72e375e064..bd38f4d330258c 100644 --- a/tests/components/esphome/test_update.py +++ b/tests/components/esphome/test_update.py @@ -1,18 +1,35 @@ """Test ESPHome update entities.""" import asyncio +from collections.abc import Awaitable, Callable import dataclasses from unittest.mock import Mock, patch +from aioesphomeapi import ( + APIClient, + EntityInfo, + EntityState, + UserService, +) import pytest -from homeassistant.components.esphome.dashboard import async_get_dashboard +from homeassistant.components.esphome.dashboard import ( + async_get_dashboard, +) from homeassistant.components.update import UpdateEntityFeature -from homeassistant.const import STATE_ON, STATE_UNAVAILABLE +from homeassistant.const import ( + STATE_OFF, + STATE_ON, + STATE_UNAVAILABLE, + STATE_UNKNOWN, +) from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.dispatcher import async_dispatcher_send +from .conftest import MockESPHomeDevice -@pytest.fixture(autouse=True) + +@pytest.fixture def stub_reconnect(): """Stub reconnect.""" with patch("homeassistant.components.esphome.manager.ReconnectLogic.start"): @@ -30,7 +47,7 @@ def stub_reconnect(): "configuration": "test.yaml", } ], - "on", + STATE_ON, { "latest_version": "2023.2.0-dev", "installed_version": "1.0.0", @@ -44,7 +61,7 @@ def stub_reconnect(): "current_version": "1.0.0", }, ], - "off", + STATE_OFF, { "latest_version": "1.0.0", "installed_version": "1.0.0", @@ -53,13 +70,14 @@ def stub_reconnect(): ), ( [], - "unavailable", + STATE_UNKNOWN, # dashboard is available but device is unknown {"supported_features": 0}, ), ], ) async def test_update_entity( hass: HomeAssistant, + stub_reconnect, mock_config_entry, mock_device_info, mock_dashboard, @@ -88,6 +106,48 @@ async def test_update_entity( if expected_state != "on": return + # Compile failed, don't try to upload + with patch( + "esphome_dashboard_api.ESPHomeDashboardAPI.compile", return_value=False + ) as mock_compile, patch( + "esphome_dashboard_api.ESPHomeDashboardAPI.upload", return_value=True + ) as mock_upload, pytest.raises( + HomeAssistantError, match="compiling" + ): + await hass.services.async_call( + "update", + "install", + {"entity_id": "update.none_firmware"}, + blocking=True, + ) + + assert len(mock_compile.mock_calls) == 1 + assert mock_compile.mock_calls[0][1][0] == "test.yaml" + + assert len(mock_upload.mock_calls) == 0 + + # Compile success, upload fails + with patch( + "esphome_dashboard_api.ESPHomeDashboardAPI.compile", return_value=True + ) as mock_compile, patch( + "esphome_dashboard_api.ESPHomeDashboardAPI.upload", return_value=False + ) as mock_upload, pytest.raises( + HomeAssistantError, match="OTA" + ): + await hass.services.async_call( + "update", + "install", + {"entity_id": "update.none_firmware"}, + blocking=True, + ) + + assert len(mock_compile.mock_calls) == 1 + assert mock_compile.mock_calls[0][1][0] == "test.yaml" + + assert len(mock_upload.mock_calls) == 1 + assert mock_upload.mock_calls[0][1][0] == "test.yaml" + + # Everything works with patch( "esphome_dashboard_api.ESPHomeDashboardAPI.compile", return_value=True ) as mock_compile, patch( @@ -109,6 +169,7 @@ async def test_update_entity( async def test_update_static_info( hass: HomeAssistant, + stub_reconnect, mock_config_entry, mock_device_info, mock_dashboard, @@ -155,6 +216,7 @@ async def test_update_static_info( ) async def test_update_device_state_for_availability( hass: HomeAssistant, + stub_reconnect, expected_disconnect_state: tuple[bool, str], mock_config_entry, mock_device_info, @@ -210,7 +272,11 @@ async def test_update_device_state_for_availability( async def test_update_entity_dashboard_not_available_startup( - hass: HomeAssistant, mock_config_entry, mock_device_info, mock_dashboard + hass: HomeAssistant, + stub_reconnect, + mock_config_entry, + mock_device_info, + mock_dashboard, ) -> None: """Test ESPHome update entity when dashboard is not available at startup.""" with patch( @@ -225,6 +291,7 @@ async def test_update_entity_dashboard_not_available_startup( mock_config_entry, "update" ) + # We have a dashboard but it is not available state = hass.states.get("update.none_firmware") assert state is None @@ -239,7 +306,7 @@ async def test_update_entity_dashboard_not_available_startup( await hass.async_block_till_done() state = hass.states.get("update.none_firmware") - assert state.state == "on" + assert state.state == STATE_ON expected_attributes = { "latest_version": "2023.2.0-dev", "installed_version": "1.0.0", @@ -247,3 +314,69 @@ async def test_update_entity_dashboard_not_available_startup( } for key, expected_value in expected_attributes.items(): assert state.attributes.get(key) == expected_value + + +async def test_update_entity_dashboard_discovered_after_startup_but_update_failed( + hass: HomeAssistant, + mock_client: APIClient, + mock_esphome_device: Callable[ + [APIClient, list[EntityInfo], list[UserService], list[EntityState]], + Awaitable[MockESPHomeDevice], + ], + mock_dashboard, +) -> None: + """Test ESPHome update entity when dashboard is discovered after startup and the first update fails.""" + with patch( + "esphome_dashboard_api.ESPHomeDashboardAPI.get_devices", + side_effect=asyncio.TimeoutError, + ): + await async_get_dashboard(hass).async_refresh() + await hass.async_block_till_done() + mock_device = await mock_esphome_device( + mock_client=mock_client, + entity_info=[], + user_service=[], + states=[], + ) + await hass.async_block_till_done() + state = hass.states.get("update.test_firmware") + assert state is None + + await mock_device.mock_disconnect(False) + + mock_dashboard["configured"] = [ + { + "name": "test", + "current_version": "2023.2.0-dev", + "configuration": "test.yaml", + } + ] + # Device goes unavailable, and dashboard becomes available + await async_get_dashboard(hass).async_refresh() + await hass.async_block_till_done() + + state = hass.states.get("update.test_firmware") + assert state is None + + # Finally both are available + await mock_device.mock_connect() + await async_get_dashboard(hass).async_refresh() + await hass.async_block_till_done() + state = hass.states.get("update.test_firmware") + assert state is not None + + +async def test_update_entity_not_present_without_dashboard( + hass: HomeAssistant, stub_reconnect, mock_config_entry, mock_device_info +) -> None: + """Test ESPHome update entity does not get created if there is no dashboard.""" + with patch( + "homeassistant.components.esphome.update.DomainData.get_entry_data", + return_value=Mock(available=True, device_info=mock_device_info), + ): + assert await hass.config_entries.async_forward_entry_setup( + mock_config_entry, "update" + ) + + state = hass.states.get("update.none_firmware") + assert state is None From 52c7ad130d0c65d7b8eb9764ebff59980037936d Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Thu, 13 Jul 2023 06:34:28 +0200 Subject: [PATCH 124/154] Add number entity to gardena (#96430) --- .coveragerc | 1 + .../components/gardena_bluetooth/__init__.py | 2 +- .../components/gardena_bluetooth/number.py | 146 ++++++++++++++++++ .../components/gardena_bluetooth/strings.json | 17 ++ 4 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 homeassistant/components/gardena_bluetooth/number.py diff --git a/.coveragerc b/.coveragerc index 703523ed3648f8..6b2870e84881af 100644 --- a/.coveragerc +++ b/.coveragerc @@ -408,6 +408,7 @@ omit = homeassistant/components/gardena_bluetooth/__init__.py homeassistant/components/gardena_bluetooth/const.py homeassistant/components/gardena_bluetooth/coordinator.py + homeassistant/components/gardena_bluetooth/number.py homeassistant/components/gardena_bluetooth/switch.py homeassistant/components/gc100/* homeassistant/components/geniushub/* diff --git a/homeassistant/components/gardena_bluetooth/__init__.py b/homeassistant/components/gardena_bluetooth/__init__.py index 05ac16381d1ddd..2954a5fe377029 100644 --- a/homeassistant/components/gardena_bluetooth/__init__.py +++ b/homeassistant/components/gardena_bluetooth/__init__.py @@ -20,7 +20,7 @@ from .const import DOMAIN from .coordinator import Coordinator, DeviceUnavailable -PLATFORMS: list[Platform] = [Platform.SWITCH] +PLATFORMS: list[Platform] = [Platform.NUMBER, Platform.SWITCH] LOGGER = logging.getLogger(__name__) TIMEOUT = 20.0 DISCONNECT_DELAY = 5 diff --git a/homeassistant/components/gardena_bluetooth/number.py b/homeassistant/components/gardena_bluetooth/number.py new file mode 100644 index 00000000000000..367e2f727bc8fc --- /dev/null +++ b/homeassistant/components/gardena_bluetooth/number.py @@ -0,0 +1,146 @@ +"""Support for number entities.""" +from __future__ import annotations + +from dataclasses import dataclass, field + +from gardena_bluetooth.const import DeviceConfiguration, Valve +from gardena_bluetooth.parse import ( + CharacteristicInt, + CharacteristicLong, + CharacteristicUInt16, +) + +from homeassistant.components.number import ( + NumberEntity, + NumberEntityDescription, + NumberMode, +) +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import EntityCategory +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from .const import DOMAIN +from .coordinator import Coordinator, GardenaBluetoothEntity + + +@dataclass +class GardenaBluetoothNumberEntityDescription(NumberEntityDescription): + """Description of entity.""" + + char: CharacteristicInt | CharacteristicUInt16 | CharacteristicLong = field( + default_factory=lambda: CharacteristicInt("") + ) + + +DESCRIPTIONS = ( + GardenaBluetoothNumberEntityDescription( + key=Valve.manual_watering_time.uuid, + translation_key="manual_watering_time", + native_unit_of_measurement="s", + mode=NumberMode.BOX, + native_min_value=0.0, + native_max_value=24 * 60 * 60, + native_step=60, + entity_category=EntityCategory.CONFIG, + char=Valve.manual_watering_time, + ), + GardenaBluetoothNumberEntityDescription( + key=Valve.remaining_open_time.uuid, + translation_key="remaining_open_time", + native_unit_of_measurement="s", + native_min_value=0.0, + native_max_value=24 * 60 * 60, + native_step=60.0, + entity_category=EntityCategory.DIAGNOSTIC, + char=Valve.remaining_open_time, + ), + GardenaBluetoothNumberEntityDescription( + key=DeviceConfiguration.rain_pause.uuid, + translation_key="rain_pause", + native_unit_of_measurement="d", + mode=NumberMode.BOX, + native_min_value=0.0, + native_max_value=127.0, + native_step=1.0, + entity_category=EntityCategory.CONFIG, + char=DeviceConfiguration.rain_pause, + ), + GardenaBluetoothNumberEntityDescription( + key=DeviceConfiguration.season_pause.uuid, + translation_key="season_pause", + native_unit_of_measurement="d", + mode=NumberMode.BOX, + native_min_value=0.0, + native_max_value=365.0, + native_step=1.0, + entity_category=EntityCategory.CONFIG, + char=DeviceConfiguration.season_pause, + ), +) + + +async def async_setup_entry( + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback +) -> None: + """Set up entity based on a config entry.""" + coordinator: Coordinator = hass.data[DOMAIN][entry.entry_id] + entities: list[NumberEntity] = [ + GardenaBluetoothNumber(coordinator, description) + for description in DESCRIPTIONS + if description.key in coordinator.characteristics + ] + entities.append(GardenaBluetoothRemainingOpenSetNumber(coordinator)) + async_add_entities(entities) + + +class GardenaBluetoothNumber(GardenaBluetoothEntity, NumberEntity): + """Representation of a number.""" + + entity_description: GardenaBluetoothNumberEntityDescription + + def __init__( + self, + coordinator: Coordinator, + description: GardenaBluetoothNumberEntityDescription, + ) -> None: + """Initialize the number entity.""" + super().__init__(coordinator, {description.key}) + self._attr_unique_id = f"{coordinator.address}-{description.key}" + self.entity_description = description + + def _handle_coordinator_update(self) -> None: + if data := self.coordinator.data.get(self.entity_description.char.uuid): + self._attr_native_value = float(self.entity_description.char.decode(data)) + else: + self._attr_native_value = None + super()._handle_coordinator_update() + + async def async_set_native_value(self, value: float) -> None: + """Set new value.""" + await self.coordinator.write(self.entity_description.char, int(value)) + self.async_write_ha_state() + + +class GardenaBluetoothRemainingOpenSetNumber(GardenaBluetoothEntity, NumberEntity): + """Representation of a entity with remaining time.""" + + _attr_translation_key = "remaining_open_set" + _attr_native_unit_of_measurement = "min" + _attr_mode = NumberMode.BOX + _attr_native_min_value = 0.0 + _attr_native_max_value = 24 * 60 + _attr_native_step = 1.0 + + def __init__( + self, + coordinator: Coordinator, + ) -> None: + """Initialize the remaining time entity.""" + super().__init__(coordinator, {Valve.remaining_open_time.uuid}) + self._attr_unique_id = f"{coordinator.address}-remaining_open_set" + + async def async_set_native_value(self, value: float) -> None: + """Set new value.""" + await self.coordinator.write(Valve.remaining_open_time, int(value * 60)) + self.async_write_ha_state() diff --git a/homeassistant/components/gardena_bluetooth/strings.json b/homeassistant/components/gardena_bluetooth/strings.json index 165e336bbecb60..c7a6e9637dffa0 100644 --- a/homeassistant/components/gardena_bluetooth/strings.json +++ b/homeassistant/components/gardena_bluetooth/strings.json @@ -19,6 +19,23 @@ } }, "entity": { + "number": { + "remaining_open_time": { + "name": "Remaining open time" + }, + "remaining_open_set": { + "name": "Open for" + }, + "manual_watering_time": { + "name": "Manual watering time" + }, + "rain_pause": { + "name": "Rain pause" + }, + "season_pause": { + "name": "Season pause" + } + }, "switch": { "state": { "name": "Open" From bc9b763688777377375a51bbce68451539bee6ab Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 12 Jul 2023 21:44:27 -1000 Subject: [PATCH 125/154] Improve performance of http auth logging (#96464) Avoid the argument lookups when debug logging is not enabled --- homeassistant/components/http/auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/http/auth.py b/homeassistant/components/http/auth.py index 77ae80b62ffacd..fc7b3c03abebb2 100644 --- a/homeassistant/components/http/auth.py +++ b/homeassistant/components/http/auth.py @@ -224,7 +224,7 @@ async def auth_middleware( authenticated = True auth_type = "signed request" - if authenticated: + if authenticated and _LOGGER.isEnabledFor(logging.DEBUG): _LOGGER.debug( "Authenticated %s for %s using %s", request.remote, From d025b97bb9317c4068b467fdebc86e4a59ed9ca9 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Thu, 13 Jul 2023 09:49:05 +0200 Subject: [PATCH 126/154] Migrate Z-Wave services to support translations (#96361) * Migrate Z-Wave services to support translations * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> --------- Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com> Co-authored-by: Martin Hjelmare --- .../components/zwave_js/services.yaml | 84 -------- .../components/zwave_js/strings.json | 188 ++++++++++++++++++ 2 files changed, 188 insertions(+), 84 deletions(-) diff --git a/homeassistant/components/zwave_js/services.yaml b/homeassistant/components/zwave_js/services.yaml index 05e2f8bd9fbbf5..e3d59ff43f75a8 100644 --- a/homeassistant/components/zwave_js/services.yaml +++ b/homeassistant/components/zwave_js/services.yaml @@ -1,105 +1,77 @@ # Describes the format for available Z-Wave services clear_lock_usercode: - name: Clear a usercode from a lock - description: Clear a usercode from a lock target: entity: domain: lock integration: zwave_js fields: code_slot: - name: Code slot - description: Code slot to clear code from required: true example: 1 selector: text: set_lock_usercode: - name: Set a usercode on a lock - description: Set a usercode on a lock target: entity: domain: lock integration: zwave_js fields: code_slot: - name: Code slot - description: Code slot to set the code. required: true example: 1 selector: text: usercode: - name: Code - description: Code to set. required: true example: 1234 selector: text: set_config_parameter: - name: Set a Z-Wave device configuration parameter - description: Allow for changing configuration parameters of your Z-Wave devices. target: entity: integration: zwave_js fields: endpoint: - name: Endpoint - description: The configuration parameter's endpoint. example: 1 default: 0 required: false selector: text: parameter: - name: Parameter - description: The (name or id of the) configuration parameter you want to configure. example: Minimum brightness level required: true selector: text: bitmask: - name: Bitmask - description: Target a specific bitmask (see the documentation for more information). advanced: true selector: text: value: - name: Value - description: The new value to set for this configuration parameter. example: 5 required: true selector: text: bulk_set_partial_config_parameters: - name: Bulk set partial configuration parameters for a Z-Wave device (Advanced). - description: Allow for bulk setting partial parameters. Useful when multiple partial parameters have to be set at the same time. target: entity: integration: zwave_js fields: endpoint: - name: Endpoint - description: The configuration parameter's endpoint. example: 1 default: 0 required: false selector: text: parameter: - name: Parameter - description: The id of the configuration parameter you want to configure. example: 9 required: true selector: text: value: - name: Value - description: The new value(s) to set for this configuration parameter. Can either be a raw integer value to represent the bulk change or a mapping where the key is the bitmask (either in hex or integer form) and the value is the new value you want to set for that partial parameter. example: | "0x1": 1 "0x10": 1 @@ -110,12 +82,8 @@ bulk_set_partial_config_parameters: object: refresh_value: - name: Refresh value(s) of a Z-Wave entity - description: Force update value(s) for a Z-Wave entity fields: entity_id: - name: Entities - description: Entities to refresh values for. required: true example: | - sensor.family_room_motion @@ -125,184 +93,132 @@ refresh_value: integration: zwave_js multiple: true refresh_all_values: - name: Refresh all values? - description: Whether to refresh all values (true) or just the primary value (false) default: false selector: boolean: set_value: - name: Set a value on a Z-Wave device (Advanced) - description: Allow for changing any value that Z-Wave JS recognizes on a Z-Wave device. This service has minimal validation so only use this service if you know what you are doing. target: entity: integration: zwave_js fields: command_class: - name: Command Class - description: The ID of the command class for the value. example: 117 required: true selector: text: endpoint: - name: Endpoint - description: The endpoint for the value. example: 1 required: false selector: text: property: - name: Property - description: The ID of the property for the value. example: currentValue required: true selector: text: property_key: - name: Property Key - description: The ID of the property key for the value example: 1 required: false selector: text: value: - name: Value - description: The new value to set. example: "ffbb99" required: true selector: object: options: - name: Options - description: Set value options map. Refer to the Z-Wave JS documentation for more information on what options can be set. required: false selector: object: wait_for_result: - name: Wait for result? - description: Whether or not to wait for a response from the node. If not included in the payload, the integration will decide whether to wait or not. If set to `true`, note that the service call can take a while if setting a value on an asleep battery device. required: false selector: boolean: multicast_set_value: - name: Set a value on multiple Z-Wave devices via multicast (Advanced) - description: Allow for changing any value that Z-Wave JS recognizes on multiple Z-Wave devices using multicast, so all devices receive the message simultaneously. This service has minimal validation so only use this service if you know what you are doing. target: entity: integration: zwave_js fields: broadcast: - name: Broadcast? - description: Whether command should be broadcast to all devices on the network. example: true required: false selector: boolean: command_class: - name: Command Class - description: The ID of the command class for the value. example: 117 required: true selector: text: endpoint: - name: Endpoint - description: The endpoint for the value. example: 1 required: false selector: text: property: - name: Property - description: The ID of the property for the value. example: currentValue required: true selector: text: property_key: - name: Property Key - description: The ID of the property key for the value example: 1 required: false selector: text: options: - name: Options - description: Set value options map. Refer to the Z-Wave JS documentation for more information on what options can be set. required: false selector: object: value: - name: Value - description: The new value to set. example: "ffbb99" required: true selector: object: ping: - name: Ping a node - description: Forces Z-Wave JS to try to reach a node. This can be used to update the status of the node in Z-Wave JS when you think it doesn't accurately reflect reality, e.g. reviving a failed/dead node or marking the node as asleep. target: entity: integration: zwave_js reset_meter: - name: Reset meter(s) on a node - description: Resets the meter(s) on a node. target: entity: domain: sensor integration: zwave_js fields: meter_type: - name: Meter Type - description: The type of meter to reset. Not all meters support the ability to pick a meter type to reset. example: 1 required: false selector: text: value: - name: Target Value - description: The value that meter(s) should be reset to. Not all meters support the ability to be reset to a specific value. example: 5 required: false selector: text: invoke_cc_api: - name: Invoke a Command Class API on a node (Advanced) - description: Allows for calling a Command Class API on a node. Some Command Classes can't be fully controlled via the `set_value` service and require direct calls to the Command Class API. target: entity: integration: zwave_js fields: command_class: - name: Command Class - description: The ID of the command class that you want to issue a command to. example: 132 required: true selector: text: endpoint: - name: Endpoint - description: The endpoint to call the API on. If an endpoint is specified, that endpoint will be targeted for all nodes associated with the target areas, devices, and/or entities. If an endpoint is not specified, the root endpoint (0) will be targeted for nodes associated with target areas and devices, and the endpoint for the primary value of each entity will be targeted. example: 1 required: false selector: text: method_name: - name: Method Name - description: The name of the API method to call. Refer to the Z-Wave JS Command Class API documentation (https://zwave-js.github.io/node-zwave-js/#/api/CCs/index) for available methods. example: setInterval required: true selector: text: parameters: - name: Parameters - description: A list of parameters to pass to the API method. Refer to the Z-Wave JS Command Class API documentation (https://zwave-js.github.io/node-zwave-js/#/api/CCs/index) for parameters. example: "[1, 1]" required: true selector: diff --git a/homeassistant/components/zwave_js/strings.json b/homeassistant/components/zwave_js/strings.json index 0bcb209a760f75..37b4577e5dfc10 100644 --- a/homeassistant/components/zwave_js/strings.json +++ b/homeassistant/components/zwave_js/strings.json @@ -151,5 +151,193 @@ "title": "Newer version of Z-Wave JS Server needed", "description": "The version of Z-Wave JS Server you are currently running is too old for this version of Home Assistant. Please update the Z-Wave JS Server to the latest version to fix this issue." } + }, + "services": { + "clear_lock_usercode": { + "name": "Clear lock user code", + "description": "Clears a user code from a lock.", + "fields": { + "code_slot": { + "name": "Code slot", + "description": "Code slot to clear code from." + } + } + }, + "set_lock_usercode": { + "name": "Set lock user code", + "description": "Sets a user code on a lock.", + "fields": { + "code_slot": { + "name": "[%key:component::zwave_js::services::clear_lock_usercode::fields::code_slot::name%]", + "description": "Code slot to set the code." + }, + "usercode": { + "name": "Code", + "description": "Lock code to set." + } + } + }, + "set_config_parameter": { + "name": "Set device configuration parameter", + "description": "Changes the configuration parameters of your Z-Wave devices.", + "fields": { + "endpoint": { + "name": "Endpoint", + "description": "The configuration parameter's endpoint." + }, + "parameter": { + "name": "Parameter", + "description": "The name (or ID) of the configuration parameter you want to configure." + }, + "bitmask": { + "name": "Bitmask", + "description": "Target a specific bitmask (see the documentation for more information)." + }, + "value": { + "name": "Value", + "description": "The new value to set for this configuration parameter." + } + } + }, + "bulk_set_partial_config_parameters": { + "name": "Bulk set partial configuration parameters (advanced).", + "description": "Allows for bulk setting partial parameters. Useful when multiple partial parameters have to be set at the same time.", + "fields": { + "endpoint": { + "name": "[%key:component::zwave_js::services::set_config_parameter::fields::endpoint::name%]", + "description": "[%key:component::zwave_js::services::set_config_parameter::fields::endpoint::description%]" + }, + "parameter": { + "name": "[%key:component::zwave_js::services::set_config_parameter::fields::parameter::name%]", + "description": "[%key:component::zwave_js::services::set_config_parameter::fields::parameter::description%]" + }, + "value": { + "name": "[%key:component::zwave_js::services::set_config_parameter::fields::value::name%]", + "description": "The new value(s) to set for this configuration parameter. Can either be a raw integer value to represent the bulk change or a mapping where the key is the bitmask (either in hex or integer form) and the value is the new value you want to set for that partial parameter." + } + } + }, + "refresh_value": { + "name": "Refresh values", + "description": "Force updates the values of a Z-Wave entity.", + "fields": { + "entity_id": { + "name": "Entities", + "description": "Entities to refresh." + }, + "refresh_all_values": { + "name": "Refresh all values?", + "description": "Whether to refresh all values (true) or just the primary value (false)." + } + } + }, + "set_value": { + "name": "Set a value (advanced)", + "description": "Changes any value that Z-Wave JS recognizes on a Z-Wave device. This service has minimal validation so only use this service if you know what you are doing.", + "fields": { + "command_class": { + "name": "Command class", + "description": "The ID of the command class for the value." + }, + "endpoint": { + "name": "[%key:component::zwave_js::services::set_config_parameter::fields::endpoint::name%]", + "description": "The endpoint for the value." + }, + "property": { + "name": "Property", + "description": "The ID of the property for the value." + }, + "property_key": { + "name": "Property key", + "description": "The ID of the property key for the value." + }, + "value": { + "name": "[%key:component::zwave_js::services::set_config_parameter::fields::value::name%]", + "description": "The new value to set." + }, + "options": { + "name": "Options", + "description": "Set value options map. Refer to the Z-Wave JS documentation for more information on what options can be set." + }, + "wait_for_result": { + "name": "Wait for result?", + "description": "Whether or not to wait for a response from the node. If not included in the payload, the integration will decide whether to wait or not. If set to `true`, note that the service call can take a while if setting a value on an asleep battery device." + } + } + }, + "multicast_set_value": { + "name": "Set a value on multiple devices via multicast (advanced)", + "description": "Changes any value that Z-Wave JS recognizes on multiple Z-Wave devices using multicast, so all devices receive the message simultaneously. This service has minimal validation so only use this service if you know what you are doing.", + "fields": { + "broadcast": { + "name": "Broadcast?", + "description": "Whether command should be broadcast to all devices on the network." + }, + "command_class": { + "name": "[%key:component::zwave_js::services::set_value::fields::command_class::name%]", + "description": "[%key:component::zwave_js::services::set_value::fields::command_class::description%]" + }, + "endpoint": { + "name": "[%key:component::zwave_js::services::set_config_parameter::fields::endpoint::name%]", + "description": "[%key:component::zwave_js::services::set_value::fields::endpoint::description%]" + }, + "property": { + "name": "[%key:component::zwave_js::services::set_value::fields::property::name%]", + "description": "[%key:component::zwave_js::services::set_value::fields::property::description%]" + }, + "property_key": { + "name": "[%key:component::zwave_js::services::set_value::fields::property_key::name%]", + "description": "[%key:component::zwave_js::services::set_value::fields::property_key::description%]" + }, + "options": { + "name": "[%key:component::zwave_js::services::set_value::fields::options::name%]", + "description": "[%key:component::zwave_js::services::set_value::fields::options::description%]" + }, + "value": { + "name": "[%key:component::zwave_js::services::set_config_parameter::fields::value::name%]", + "description": "[%key:component::zwave_js::services::set_value::fields::value::description%]" + } + } + }, + "ping": { + "name": "Ping a node", + "description": "Forces Z-Wave JS to try to reach a node. This can be used to update the status of the node in Z-Wave JS when you think it doesn't accurately reflect reality, e.g. reviving a failed/dead node or marking the node as asleep." + }, + "reset_meter": { + "name": "Reset meters on a node", + "description": "Resets the meters on a node.", + "fields": { + "meter_type": { + "name": "Meter type", + "description": "The type of meter to reset. Not all meters support the ability to pick a meter type to reset." + }, + "value": { + "name": "Target value", + "description": "The value that meters should be reset to. Not all meters support the ability to be reset to a specific value." + } + } + }, + "invoke_cc_api": { + "name": "Invoke a Command Class API on a node (advanced)", + "description": "Calls a Command Class API on a node. Some Command Classes can't be fully controlled via the `set_value` service and require direct calls to the Command Class API.", + "fields": { + "command_class": { + "name": "[%key:component::zwave_js::services::set_value::fields::command_class::name%]", + "description": "The ID of the command class that you want to issue a command to." + }, + "endpoint": { + "name": "[%key:component::zwave_js::services::set_config_parameter::fields::endpoint::name%]", + "description": "The endpoint to call the API on. If an endpoint is specified, that endpoint will be targeted for all nodes associated with the target areas, devices, and/or entities. If an endpoint is not specified, the root endpoint (0) will be targeted for nodes associated with target areas and devices, and the endpoint for the primary value of each entity will be targeted." + }, + "method_name": { + "name": "Method name", + "description": "The name of the API method to call. Refer to the Z-Wave JS Command Class API documentation (https://zwave-js.github.io/node-zwave-js/#/api/CCs/index) for available methods." + }, + "parameters": { + "name": "Parameters", + "description": "A list of parameters to pass to the API method. Refer to the Z-Wave JS Command Class API documentation (https://zwave-js.github.io/node-zwave-js/#/api/CCs/index) for parameters." + } + } + } } } From b8bc958070a152d354fb0dabb30e888cc2f79056 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Thu, 13 Jul 2023 15:05:55 +0200 Subject: [PATCH 127/154] Use device class translations in airvisual pro (#96472) --- homeassistant/components/airvisual_pro/sensor.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/homeassistant/components/airvisual_pro/sensor.py b/homeassistant/components/airvisual_pro/sensor.py index 59de2ae630cefd..5f64e38c4a3c0a 100644 --- a/homeassistant/components/airvisual_pro/sensor.py +++ b/homeassistant/components/airvisual_pro/sensor.py @@ -43,7 +43,6 @@ class AirVisualProMeasurementDescription( SENSOR_DESCRIPTIONS = ( AirVisualProMeasurementDescription( key="air_quality_index", - name="Air quality index", device_class=SensorDeviceClass.AQI, state_class=SensorStateClass.MEASUREMENT, value_fn=lambda settings, status, measurements: measurements[ @@ -52,7 +51,6 @@ class AirVisualProMeasurementDescription( ), AirVisualProMeasurementDescription( key="battery_level", - name="Battery", device_class=SensorDeviceClass.BATTERY, entity_category=EntityCategory.DIAGNOSTIC, native_unit_of_measurement=PERCENTAGE, @@ -60,7 +58,6 @@ class AirVisualProMeasurementDescription( ), AirVisualProMeasurementDescription( key="carbon_dioxide", - name="C02", device_class=SensorDeviceClass.CO2, native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION, state_class=SensorStateClass.MEASUREMENT, @@ -68,7 +65,6 @@ class AirVisualProMeasurementDescription( ), AirVisualProMeasurementDescription( key="humidity", - name="Humidity", device_class=SensorDeviceClass.HUMIDITY, native_unit_of_measurement=PERCENTAGE, value_fn=lambda settings, status, measurements: measurements["humidity"], @@ -91,7 +87,6 @@ class AirVisualProMeasurementDescription( ), AirVisualProMeasurementDescription( key="particulate_matter_2_5", - name="PM 2.5", device_class=SensorDeviceClass.PM25, native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, state_class=SensorStateClass.MEASUREMENT, @@ -99,7 +94,6 @@ class AirVisualProMeasurementDescription( ), AirVisualProMeasurementDescription( key="temperature", - name="Temperature", device_class=SensorDeviceClass.TEMPERATURE, native_unit_of_measurement=UnitOfTemperature.CELSIUS, state_class=SensorStateClass.MEASUREMENT, @@ -107,7 +101,6 @@ class AirVisualProMeasurementDescription( ), AirVisualProMeasurementDescription( key="voc", - name="VOC", device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS, native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, state_class=SensorStateClass.MEASUREMENT, From c54ceb2da21fe0595326923cfdab65206f8a8f57 Mon Sep 17 00:00:00 2001 From: RenierM26 <66512715+RenierM26@users.noreply.github.com> Date: Thu, 13 Jul 2023 17:03:26 +0200 Subject: [PATCH 128/154] ImageEntity split load_image_from_url (#96146) * Initial commit * fix async_load_image_from_url --- homeassistant/components/image/__init__.py | 37 +++++++++++++--------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/image/__init__.py b/homeassistant/components/image/__init__.py index 8daea2cdd46051..e4bc1664fd9369 100644 --- a/homeassistant/components/image/__init__.py +++ b/homeassistant/components/image/__init__.py @@ -167,18 +167,14 @@ def image(self) -> bytes | None: """Return bytes of image.""" raise NotImplementedError() - async def _async_load_image_from_url(self, url: str) -> Image | None: - """Load an image by url.""" + async def _fetch_url(self, url: str) -> httpx.Response | None: + """Fetch a URL.""" try: response = await self._client.get( url, timeout=GET_IMAGE_TIMEOUT, follow_redirects=True ) response.raise_for_status() - content_type = response.headers.get("content-type") - return Image( - content=response.content, - content_type=valid_image_content_type(content_type), - ) + return response except httpx.TimeoutException: _LOGGER.error("%s: Timeout getting image from %s", self.entity_id, url) return None @@ -190,14 +186,25 @@ async def _async_load_image_from_url(self, url: str) -> Image | None: err, ) return None - except ImageContentTypeError: - _LOGGER.error( - "%s: Image from %s has invalid content type: %s", - self.entity_id, - url, - content_type, - ) - return None + + async def _async_load_image_from_url(self, url: str) -> Image | None: + """Load an image by url.""" + if response := await self._fetch_url(url): + content_type = response.headers.get("content-type") + try: + return Image( + content=response.content, + content_type=valid_image_content_type(content_type), + ) + except ImageContentTypeError: + _LOGGER.error( + "%s: Image from %s has invalid content type: %s", + self.entity_id, + url, + content_type, + ) + return None + return None async def async_image(self) -> bytes | None: """Return bytes of image.""" From 7859be6481f67384890ff2de44ba4016bec03b17 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 13 Jul 2023 11:52:50 -0400 Subject: [PATCH 129/154] Add deduplicate translations script (#96384) * Add deduplicate script * Fix forecast_solar incorrect key with space * Fix utf-8 * Do not create references to other arbitrary other integrations * Add commented code to only allow applying to referencing integrations * Tweak * Bug fix * Add command line arg for limit reference * never suggest to update common keys * Output of script * Apply suggestions from code review Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com> --------- Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com> --- homeassistant/components/abode/strings.json | 2 +- homeassistant/components/adguard/strings.json | 10 +- .../components/aftership/strings.json | 4 +- homeassistant/components/airly/strings.json | 2 +- .../components/airvisual/strings.json | 4 +- .../components/alarmdecoder/strings.json | 8 +- .../components/amberelectric/strings.json | 2 +- .../components/androidtv/strings.json | 10 +- homeassistant/components/anova/strings.json | 2 +- .../components/apple_tv/strings.json | 2 +- .../components/aussie_broadband/strings.json | 4 +- .../components/azure_devops/strings.json | 2 +- homeassistant/components/baf/strings.json | 2 +- homeassistant/components/blink/strings.json | 4 +- .../components/bluetooth/strings.json | 2 +- homeassistant/components/bond/strings.json | 6 +- .../components/braviatv/strings.json | 4 +- homeassistant/components/brother/strings.json | 2 +- homeassistant/components/browser/strings.json | 2 +- .../components/buienradar/strings.json | 2 +- homeassistant/components/cast/strings.json | 10 +- .../components/co2signal/strings.json | 10 +- .../components/color_extractor/strings.json | 4 +- .../components/cpuspeed/strings.json | 2 +- .../components/crownstone/strings.json | 12 +- homeassistant/components/deconz/strings.json | 10 +- homeassistant/components/demo/strings.json | 2 +- .../components/derivative/strings.json | 2 +- .../devolo_home_control/strings.json | 4 +- homeassistant/components/discord/strings.json | 2 +- .../components/dlna_dmr/strings.json | 2 +- homeassistant/components/dnsip/strings.json | 4 +- .../components/downloader/strings.json | 2 +- homeassistant/components/dsmr/strings.json | 8 +- .../components/dynalite/strings.json | 8 +- homeassistant/components/ecobee/strings.json | 6 +- .../components/eight_sleep/strings.json | 2 +- homeassistant/components/elkm1/strings.json | 14 +- homeassistant/components/elmax/strings.json | 2 +- homeassistant/components/enocean/strings.json | 2 +- homeassistant/components/esphome/strings.json | 2 +- homeassistant/components/evohome/strings.json | 2 +- homeassistant/components/facebox/strings.json | 2 +- .../components/flux_led/strings.json | 4 +- .../components/forecast_solar/strings.json | 8 +- homeassistant/components/fritz/strings.json | 14 +- .../components/fully_kiosk/strings.json | 2 +- .../components/gardena_bluetooth/strings.json | 2 +- .../components/geniushub/strings.json | 6 +- homeassistant/components/google/strings.json | 10 +- .../strings.json | 2 +- .../components/google_mail/strings.json | 2 +- homeassistant/components/group/strings.json | 16 +- .../components/growatt_server/strings.json | 42 +-- .../components/guardian/strings.json | 14 +- .../components/habitica/strings.json | 8 +- homeassistant/components/harmony/strings.json | 2 +- homeassistant/components/hassio/strings.json | 6 +- .../components/hdmi_cec/strings.json | 4 +- homeassistant/components/heos/strings.json | 4 +- .../components/here_travel_time/strings.json | 12 +- homeassistant/components/hive/strings.json | 6 +- .../components/home_connect/strings.json | 36 +-- .../components/homeassistant/strings.json | 4 +- .../homekit_controller/strings.json | 8 +- .../components/homematic/strings.json | 16 +- .../components/homematicip_cloud/strings.json | 20 +- .../components/huawei_lte/strings.json | 8 +- homeassistant/components/hue/strings.json | 16 +- .../hunterdouglas_powerview/strings.json | 2 +- .../components/hvv_departures/strings.json | 2 +- homeassistant/components/icloud/strings.json | 6 +- homeassistant/components/ifttt/strings.json | 4 +- homeassistant/components/ihc/strings.json | 24 +- homeassistant/components/insteon/strings.json | 22 +- .../components/integration/strings.json | 2 +- homeassistant/components/iperf3/strings.json | 2 +- homeassistant/components/ipp/strings.json | 2 +- homeassistant/components/isy994/strings.json | 12 +- homeassistant/components/izone/strings.json | 4 +- .../components/jvc_projector/strings.json | 2 +- .../components/kaleidescape/strings.json | 2 +- homeassistant/components/kef/strings.json | 18 +- .../components/keymitt_ble/strings.json | 4 +- homeassistant/components/knx/strings.json | 20 +- .../components/konnected/strings.json | 4 +- .../components/lametric/strings.json | 4 +- homeassistant/components/lastfm/strings.json | 6 +- homeassistant/components/lcn/strings.json | 50 +-- homeassistant/components/lifx/strings.json | 16 +- .../components/litterrobot/strings.json | 2 +- .../components/local_ip/strings.json | 2 +- homeassistant/components/logbook/strings.json | 2 +- .../components/logi_circle/strings.json | 4 +- .../components/lovelace/strings.json | 2 +- .../components/lutron_caseta/strings.json | 4 +- homeassistant/components/matter/strings.json | 2 +- homeassistant/components/mazda/strings.json | 4 +- .../components/meteo_france/strings.json | 2 +- .../components/microsoft_face/strings.json | 12 +- homeassistant/components/min_max/strings.json | 4 +- homeassistant/components/minio/strings.json | 14 +- homeassistant/components/mjpeg/strings.json | 4 +- homeassistant/components/modbus/strings.json | 18 +- .../components/modem_callerid/strings.json | 2 +- .../components/modern_forms/strings.json | 4 +- .../components/monoprice/strings.json | 12 +- homeassistant/components/mqtt/strings.json | 2 +- .../components/mysensors/strings.json | 30 +- homeassistant/components/nest/strings.json | 12 +- homeassistant/components/netatmo/strings.json | 6 +- .../components/netgear_lte/strings.json | 8 +- .../components/nibe_heatpump/strings.json | 2 +- homeassistant/components/nina/strings.json | 18 +- .../components/nissan_leaf/strings.json | 4 +- homeassistant/components/nx584/strings.json | 2 +- homeassistant/components/ombi/strings.json | 10 +- homeassistant/components/onewire/strings.json | 2 +- .../components/opentherm_gw/strings.json | 44 +-- .../components/openweathermap/strings.json | 2 +- homeassistant/components/overkiz/strings.json | 2 +- .../persistent_notification/strings.json | 2 +- .../components/profiler/strings.json | 2 +- .../components/prusalink/strings.json | 4 +- .../components/purpleair/strings.json | 2 +- homeassistant/components/qnap/strings.json | 6 +- homeassistant/components/qvr_pro/strings.json | 2 +- homeassistant/components/rachio/strings.json | 4 +- .../components/rainbird/strings.json | 2 +- .../components/rainmachine/strings.json | 22 +- .../components/recorder/strings.json | 2 +- .../components/remember_the_milk/strings.json | 2 +- homeassistant/components/renault/strings.json | 10 +- homeassistant/components/rfxtrx/strings.json | 4 +- .../components/roborock/strings.json | 12 +- .../components/rtsp_to_webrtc/strings.json | 4 +- homeassistant/components/sabnzbd/strings.json | 4 +- .../components/screenlogic/strings.json | 4 +- homeassistant/components/sfr_box/strings.json | 2 +- homeassistant/components/shelly/strings.json | 4 +- .../components/shopping_list/strings.json | 10 +- .../components/simplisafe/strings.json | 4 +- .../components/smarttub/strings.json | 4 +- homeassistant/components/sms/strings.json | 30 +- homeassistant/components/snips/strings.json | 10 +- homeassistant/components/snooz/strings.json | 2 +- homeassistant/components/songpal/strings.json | 2 +- homeassistant/components/sonos/strings.json | 4 +- .../components/soundtouch/strings.json | 6 +- homeassistant/components/spotify/strings.json | 6 +- .../components/squeezebox/strings.json | 4 +- .../components/starline/strings.json | 2 +- .../components/starlink/strings.json | 4 +- .../components/steamist/strings.json | 2 +- homeassistant/components/subaru/strings.json | 6 +- .../components/surepetcare/strings.json | 2 +- .../components/synology_dsm/strings.json | 2 +- .../components/system_bridge/strings.json | 14 +- .../components/tankerkoenig/strings.json | 2 +- .../components/telegram_bot/strings.json | 288 +++++++++--------- .../components/threshold/strings.json | 2 +- homeassistant/components/tile/strings.json | 2 +- homeassistant/components/tod/strings.json | 2 +- homeassistant/components/tplink/strings.json | 10 +- .../components/transmission/strings.json | 18 +- homeassistant/components/tuya/strings.json | 12 +- homeassistant/components/unifi/strings.json | 2 +- .../components/unifiprotect/strings.json | 12 +- homeassistant/components/upb/strings.json | 18 +- homeassistant/components/upnp/strings.json | 2 +- .../components/uptimerobot/strings.json | 2 +- .../components/utility_meter/strings.json | 2 +- homeassistant/components/vallox/strings.json | 4 +- homeassistant/components/velbus/strings.json | 12 +- homeassistant/components/vera/strings.json | 4 +- .../components/verisure/strings.json | 4 +- homeassistant/components/vizio/strings.json | 2 +- homeassistant/components/vulcan/strings.json | 6 +- homeassistant/components/webostv/strings.json | 6 +- .../components/whirlpool/strings.json | 2 +- homeassistant/components/wiz/strings.json | 2 +- .../components/wolflink/strings.json | 4 +- homeassistant/components/workday/strings.json | 4 +- .../components/xiaomi_aqara/strings.json | 12 +- .../components/xiaomi_miio/strings.json | 40 +-- .../components/yale_smart_alarm/strings.json | 2 +- homeassistant/components/yamaha/strings.json | 2 +- .../components/yamaha_musiccast/strings.json | 4 +- .../components/yeelight/strings.json | 22 +- homeassistant/components/youtube/strings.json | 4 +- homeassistant/components/zamg/strings.json | 2 +- homeassistant/components/zha/strings.json | 36 +-- .../components/zoneminder/strings.json | 2 +- .../components/zwave_js/strings.json | 38 +-- .../components/zwave_me/strings.json | 2 +- script/translations/deduplicate.py | 131 ++++++++ script/translations/develop.py | 3 +- script/translations/util.py | 10 +- 198 files changed, 1004 insertions(+), 846 deletions(-) create mode 100644 script/translations/deduplicate.py diff --git a/homeassistant/components/abode/strings.json b/homeassistant/components/abode/strings.json index c0c32d487941b2..4b98b69eb19f02 100644 --- a/homeassistant/components/abode/strings.json +++ b/homeassistant/components/abode/strings.json @@ -15,7 +15,7 @@ } }, "reauth_confirm": { - "title": "Fill in your Abode login information", + "title": "[%key:component::abode::config::step::user::title%]", "data": { "username": "[%key:common::config_flow::data::email%]", "password": "[%key:common::config_flow::data::password%]" diff --git a/homeassistant/components/adguard/strings.json b/homeassistant/components/adguard/strings.json index 95ce968a67f778..e34a7c88229926 100644 --- a/homeassistant/components/adguard/strings.json +++ b/homeassistant/components/adguard/strings.json @@ -79,11 +79,11 @@ "description": "Add a new filter subscription to AdGuard Home.", "fields": { "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "The name of the filter subscription." }, "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "The filter URL to subscribe to, containing the filter rules." } } @@ -93,7 +93,7 @@ "description": "Removes a filter subscription from AdGuard Home.", "fields": { "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "The filter subscription URL to remove." } } @@ -103,7 +103,7 @@ "description": "Enables a filter subscription in AdGuard Home.", "fields": { "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "The filter subscription URL to enable." } } @@ -113,7 +113,7 @@ "description": "Disables a filter subscription in AdGuard Home.", "fields": { "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "The filter subscription URL to disable." } } diff --git a/homeassistant/components/aftership/strings.json b/homeassistant/components/aftership/strings.json index 602138e82f58aa..a7ccdd48202176 100644 --- a/homeassistant/components/aftership/strings.json +++ b/homeassistant/components/aftership/strings.json @@ -23,11 +23,11 @@ "description": "Removes a tracking number from Aftership.", "fields": { "tracking_number": { - "name": "Tracking number", + "name": "[%key:component::aftership::services::add_tracking::fields::tracking_number::name%]", "description": "Tracking number of the tracking to remove." }, "slug": { - "name": "Slug", + "name": "[%key:component::aftership::services::add_tracking::fields::slug::name%]", "description": "Slug (carrier) of the tracking to remove." } } diff --git a/homeassistant/components/airly/strings.json b/homeassistant/components/airly/strings.json index 7ec58ccd8e51be..33ee8bbe4c95f4 100644 --- a/homeassistant/components/airly/strings.json +++ b/homeassistant/components/airly/strings.json @@ -17,7 +17,7 @@ }, "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_location%]", - "wrong_location": "No Airly measuring stations in this area." + "wrong_location": "[%key:component::airly::config::error::wrong_location%]" } }, "system_health": { diff --git a/homeassistant/components/airvisual/strings.json b/homeassistant/components/airvisual/strings.json index 0ba99c0984a575..397a41bf24b22e 100644 --- a/homeassistant/components/airvisual/strings.json +++ b/homeassistant/components/airvisual/strings.json @@ -11,7 +11,7 @@ } }, "geography_by_name": { - "title": "Configure a Geography", + "title": "[%key:component::airvisual::config::step::geography_by_coords::title%]", "description": "Use the AirVisual cloud API to monitor a city/state/country.", "data": { "api_key": "[%key:common::config_flow::data::api_key%]", @@ -45,7 +45,7 @@ "options": { "step": { "init": { - "title": "Configure AirVisual", + "title": "[%key:component::airvisual::config::step::user::title%]", "data": { "show_on_map": "Show monitored geography on the map" } diff --git a/homeassistant/components/alarmdecoder/strings.json b/homeassistant/components/alarmdecoder/strings.json index 585db4b1fa32e7..d7ac882bb827d3 100644 --- a/homeassistant/components/alarmdecoder/strings.json +++ b/homeassistant/components/alarmdecoder/strings.json @@ -37,7 +37,7 @@ } }, "arm_settings": { - "title": "Configure AlarmDecoder", + "title": "[%key:component::alarmdecoder::options::step::init::title%]", "data": { "auto_bypass": "Auto Bypass on Arm", "code_arm_required": "Code Required for Arming", @@ -45,14 +45,14 @@ } }, "zone_select": { - "title": "Configure AlarmDecoder", + "title": "[%key:component::alarmdecoder::options::step::init::title%]", "description": "Enter the zone number you'd like to to add, edit, or remove.", "data": { "zone_number": "Zone Number" } }, "zone_details": { - "title": "Configure AlarmDecoder", + "title": "[%key:component::alarmdecoder::options::step::init::title%]", "description": "Enter details for zone {zone_number}. To delete zone {zone_number}, leave Zone Name blank.", "data": { "zone_name": "Zone Name", @@ -77,7 +77,7 @@ "description": "Sends custom keypresses to the alarm.", "fields": { "keypress": { - "name": "Key press", + "name": "[%key:component::alarmdecoder::services::alarm_keypress::name%]", "description": "String to send to the alarm panel." } } diff --git a/homeassistant/components/amberelectric/strings.json b/homeassistant/components/amberelectric/strings.json index 5235a8bf325e8f..ccdc2374142f0b 100644 --- a/homeassistant/components/amberelectric/strings.json +++ b/homeassistant/components/amberelectric/strings.json @@ -3,7 +3,7 @@ "step": { "user": { "data": { - "api_token": "API Token", + "api_token": "[%key:common::config_flow::data::api_token%]", "site_id": "Site ID" }, "description": "Go to {api_url} to generate an API key" diff --git a/homeassistant/components/androidtv/strings.json b/homeassistant/components/androidtv/strings.json index 9eb3d14a2253b1..7949c066916360 100644 --- a/homeassistant/components/androidtv/strings.json +++ b/homeassistant/components/androidtv/strings.json @@ -50,7 +50,7 @@ "title": "Configure Android state detection rules", "description": "Configure detection rule for application id {rule_id}", "data": { - "rule_id": "Application ID", + "rule_id": "[%key:component::androidtv::options::step::apps::data::app_id%]", "rule_values": "List of state detection rules (see documentation)", "rule_delete": "Check to delete this rule" } @@ -90,12 +90,12 @@ "description": "Uploads a file from your Home Assistant instance to an Android / Fire TV device.", "fields": { "device_path": { - "name": "Device path", - "description": "The filepath on the Android / Fire TV device." + "name": "[%key:component::androidtv::services::download::fields::device_path::name%]", + "description": "[%key:component::androidtv::services::download::fields::device_path::description%]" }, "local_path": { - "name": "Local path", - "description": "The filepath on your Home Assistant instance." + "name": "[%key:component::androidtv::services::download::fields::local_path::name%]", + "description": "[%key:component::androidtv::services::download::fields::local_path::description%]" } } }, diff --git a/homeassistant/components/anova/strings.json b/homeassistant/components/anova/strings.json index b14246a392d78e..b7762732303087 100644 --- a/homeassistant/components/anova/strings.json +++ b/homeassistant/components/anova/strings.json @@ -29,7 +29,7 @@ "name": "State" }, "mode": { - "name": "Mode" + "name": "[%key:common::config_flow::data::mode%]" }, "target_temperature": { "name": "Target temperature" diff --git a/homeassistant/components/apple_tv/strings.json b/homeassistant/components/apple_tv/strings.json index e5948a54a8d924..8730ffe01d5947 100644 --- a/homeassistant/components/apple_tv/strings.json +++ b/homeassistant/components/apple_tv/strings.json @@ -6,7 +6,7 @@ "title": "Set up a new Apple TV", "description": "Start by entering the device name (e.g. Kitchen or Bedroom) or IP address of the Apple TV you want to add.\n\nIf you cannot see your device or experience any issues, try specifying the device IP address.", "data": { - "device_input": "Device" + "device_input": "[%key:common::config_flow::data::device%]" } }, "reconfigure": { diff --git a/homeassistant/components/aussie_broadband/strings.json b/homeassistant/components/aussie_broadband/strings.json index 90e4f094ee6fb4..276844a88066be 100644 --- a/homeassistant/components/aussie_broadband/strings.json +++ b/homeassistant/components/aussie_broadband/strings.json @@ -35,9 +35,9 @@ "options": { "step": { "init": { - "title": "Select Services", + "title": "[%key:component::aussie_broadband::config::step::service::title%]", "data": { - "services": "Services" + "services": "[%key:component::aussie_broadband::config::step::service::data::services%]" } } }, diff --git a/homeassistant/components/azure_devops/strings.json b/homeassistant/components/azure_devops/strings.json index 8dfd203c84b626..ad8ebaa016ede8 100644 --- a/homeassistant/components/azure_devops/strings.json +++ b/homeassistant/components/azure_devops/strings.json @@ -18,7 +18,7 @@ }, "reauth": { "data": { - "personal_access_token": "Personal Access Token (PAT)" + "personal_access_token": "[%key:component::azure_devops::config::step::user::data::personal_access_token%]" }, "description": "Authentication failed for {project_url}. Please enter your current credentials.", "title": "Reauthentication" diff --git a/homeassistant/components/baf/strings.json b/homeassistant/components/baf/strings.json index cb322320675b2a..5143b519d2788e 100644 --- a/homeassistant/components/baf/strings.json +++ b/homeassistant/components/baf/strings.json @@ -60,7 +60,7 @@ "name": "Wi-Fi SSID" }, "ip_address": { - "name": "IP Address" + "name": "[%key:common::config_flow::data::ip%]" } }, "switch": { diff --git a/homeassistant/components/blink/strings.json b/homeassistant/components/blink/strings.json index 6c07d1fea5513f..85556bbcd5a132 100644 --- a/homeassistant/components/blink/strings.json +++ b/homeassistant/components/blink/strings.json @@ -63,7 +63,7 @@ "description": "Saves last recorded video clip to local file.", "fields": { "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "Name of camera to grab video from." }, "filename": { @@ -77,7 +77,7 @@ "description": "Saves all recent video clips to local directory with file pattern \"%Y%m%d_%H%M%S_{name}.mp4\".", "fields": { "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "Name of camera to grab recent clips from." }, "file_path": { diff --git a/homeassistant/components/bluetooth/strings.json b/homeassistant/components/bluetooth/strings.json index cae88ef24c19c8..4b1681262510af 100644 --- a/homeassistant/components/bluetooth/strings.json +++ b/homeassistant/components/bluetooth/strings.json @@ -5,7 +5,7 @@ "user": { "description": "Choose a device to set up", "data": { - "address": "Device" + "address": "[%key:common::config_flow::data::device%]" } }, "bluetooth_confirm": { diff --git a/homeassistant/components/bond/strings.json b/homeassistant/components/bond/strings.json index 04be198d149683..4c7c224bc44edf 100644 --- a/homeassistant/components/bond/strings.json +++ b/homeassistant/components/bond/strings.json @@ -60,11 +60,11 @@ "fields": { "entity_id": { "name": "Entity", - "description": "Name(s) of entities to set the tracked power state of." + "description": "[%key:component::bond::services::set_switch_power_tracked_state::fields::entity_id::description%]" }, "power_state": { - "name": "Power state", - "description": "Power state." + "name": "[%key:component::bond::services::set_switch_power_tracked_state::fields::power_state::name%]", + "description": "[%key:component::bond::services::set_switch_power_tracked_state::fields::power_state::description%]" } } }, diff --git a/homeassistant/components/braviatv/strings.json b/homeassistant/components/braviatv/strings.json index aacaf81465b327..30ad296554cd59 100644 --- a/homeassistant/components/braviatv/strings.json +++ b/homeassistant/components/braviatv/strings.json @@ -15,14 +15,14 @@ } }, "pin": { - "title": "Authorize Sony Bravia TV", + "title": "[%key:component::braviatv::config::step::authorize::title%]", "description": "Enter the PIN code shown on the Sony Bravia TV. \n\nIf the PIN code is not shown, you have to unregister Home Assistant on your TV, go to: Settings -> Network -> Remote device settings -> Deregister remote device.", "data": { "pin": "[%key:common::config_flow::data::pin%]" } }, "psk": { - "title": "Authorize Sony Bravia TV", + "title": "[%key:component::braviatv::config::step::authorize::title%]", "description": "To set up PSK on your TV, go to: Settings -> Network -> Home Network Setup -> IP Control. Set «Authentication» to «Normal and Pre-Shared Key» or «Pre-Shared Key» and define your Pre-Shared-Key string (e.g. sony). \n\nThen enter your PSK here.", "data": { "pin": "PSK" diff --git a/homeassistant/components/brother/strings.json b/homeassistant/components/brother/strings.json index 3ee3fe7609ff60..641b1dbadf3319 100644 --- a/homeassistant/components/brother/strings.json +++ b/homeassistant/components/brother/strings.json @@ -12,7 +12,7 @@ "description": "Do you want to add the printer {model} with serial number `{serial_number}` to Home Assistant?", "title": "Discovered Brother Printer", "data": { - "type": "Type of the printer" + "type": "[%key:component::brother::config::step::user::data::type%]" } } }, diff --git a/homeassistant/components/browser/strings.json b/homeassistant/components/browser/strings.json index fafd5fb96b006f..9083ba93795b4e 100644 --- a/homeassistant/components/browser/strings.json +++ b/homeassistant/components/browser/strings.json @@ -5,7 +5,7 @@ "description": "Opens a URL in the default browser on the host machine of Home Assistant.", "fields": { "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "The URL to open." } } diff --git a/homeassistant/components/buienradar/strings.json b/homeassistant/components/buienradar/strings.json index bac4e63e288fe6..f254f7602f889f 100644 --- a/homeassistant/components/buienradar/strings.json +++ b/homeassistant/components/buienradar/strings.json @@ -38,7 +38,7 @@ "name": "Barometer" }, "barometerfcnamenl": { - "name": "Barometer" + "name": "[%key:component::buienradar::entity::sensor::barometerfcname::name%]" }, "condition": { "name": "Condition", diff --git a/homeassistant/components/cast/strings.json b/homeassistant/components/cast/strings.json index 4de0f85851f307..ce622e48aaec3f 100644 --- a/homeassistant/components/cast/strings.json +++ b/homeassistant/components/cast/strings.json @@ -22,15 +22,15 @@ "options": { "step": { "basic_options": { - "title": "Google Cast configuration", - "description": "Known Hosts - A comma-separated list of hostnames or IP-addresses of cast devices, use if mDNS discovery is not working.", + "title": "[%key:component::cast::config::step::config::title%]", + "description": "[%key:component::cast::config::step::config::description%]", "data": { - "known_hosts": "Known hosts" + "known_hosts": "[%key:component::cast::config::step::config::data::known_hosts%]" } }, "advanced_options": { "title": "Advanced Google Cast configuration", - "description": "Allowed UUIDs - A comma-separated list of UUIDs of Cast devices to add to Home Assistant. Use only if you don\u2019t want to add all available cast devices.\nIgnore CEC - A comma-separated list of Chromecasts that should ignore CEC data for determining the active input. This will be passed to pychromecast.IGNORE_CEC.", + "description": "Allowed UUIDs - A comma-separated list of UUIDs of Cast devices to add to Home Assistant. Use only if you don’t want to add all available cast devices.\nIgnore CEC - A comma-separated list of Chromecasts that should ignore CEC data for determining the active input. This will be passed to pychromecast.IGNORE_CEC.", "data": { "ignore_cec": "Ignore CEC", "uuid": "Allowed UUIDs" @@ -38,7 +38,7 @@ } }, "error": { - "invalid_known_hosts": "Known hosts must be a comma separated list of hosts." + "invalid_known_hosts": "[%key:component::cast::config::error::invalid_known_hosts%]" } }, "services": { diff --git a/homeassistant/components/co2signal/strings.json b/homeassistant/components/co2signal/strings.json index 05ea76f3179899..78274b0586cfdf 100644 --- a/homeassistant/components/co2signal/strings.json +++ b/homeassistant/components/co2signal/strings.json @@ -28,13 +28,17 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", "unknown": "[%key:common::config_flow::error::unknown%]", - "api_ratelimit": "API Ratelimit exceeded" + "api_ratelimit": "[%key:component::co2signal::config::error::api_ratelimit%]" } }, "entity": { "sensor": { - "carbon_intensity": { "name": "CO2 intensity" }, - "fossil_fuel_percentage": { "name": "Grid fossil fuel percentage" } + "carbon_intensity": { + "name": "CO2 intensity" + }, + "fossil_fuel_percentage": { + "name": "Grid fossil fuel percentage" + } } } } diff --git a/homeassistant/components/color_extractor/strings.json b/homeassistant/components/color_extractor/strings.json index f56a4e514b7af7..3dc02f5603016c 100644 --- a/homeassistant/components/color_extractor/strings.json +++ b/homeassistant/components/color_extractor/strings.json @@ -5,11 +5,11 @@ "description": "Sets the light RGB to the predominant color found in the image provided by URL or file path.", "fields": { "color_extract_url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "The URL of the image we want to extract RGB values from. Must be allowed in allowlist_external_urls." }, "color_extract_path": { - "name": "Path", + "name": "[%key:common::config_flow::data::path%]", "description": "The full system path to the image we want to extract RGB values from. Must be allowed in allowlist_external_dirs." } } diff --git a/homeassistant/components/cpuspeed/strings.json b/homeassistant/components/cpuspeed/strings.json index a64e1be7fcf114..e82c6a0db12603 100644 --- a/homeassistant/components/cpuspeed/strings.json +++ b/homeassistant/components/cpuspeed/strings.json @@ -3,7 +3,7 @@ "config": { "step": { "user": { - "title": "CPU Speed", + "title": "[%key:component::cpuspeed::title%]", "description": "[%key:common::config_flow::description::confirm_setup%]" } }, diff --git a/homeassistant/components/crownstone/strings.json b/homeassistant/components/crownstone/strings.json index bcd818effb08ce..204f43768c7ae3 100644 --- a/homeassistant/components/crownstone/strings.json +++ b/homeassistant/components/crownstone/strings.json @@ -53,22 +53,22 @@ "data": { "usb_path": "[%key:common::config_flow::data::usb_path%]" }, - "title": "Crownstone USB dongle configuration", + "title": "[%key:component::crownstone::config::step::usb_config::title%]", "description": "Select the serial port of the Crownstone USB dongle.\n\nLook for a device with VID 10C4 and PID EA60." }, "usb_manual_config": { "data": { "usb_manual_path": "[%key:common::config_flow::data::usb_path%]" }, - "title": "Crownstone USB dongle manual path", - "description": "Manually enter the path of a Crownstone USB dongle." + "title": "[%key:component::crownstone::config::step::usb_manual_config::title%]", + "description": "[%key:component::crownstone::config::step::usb_manual_config::description%]" }, "usb_sphere_config": { "data": { - "usb_sphere": "Crownstone Sphere" + "usb_sphere": "[%key:component::crownstone::config::step::usb_sphere_config::data::usb_sphere%]" }, - "title": "Crownstone USB Sphere", - "description": "Select a Crownstone Sphere where the USB is located." + "title": "[%key:component::crownstone::config::step::usb_sphere_config::title%]", + "description": "[%key:component::crownstone::config::step::usb_sphere_config::description%]" } } } diff --git a/homeassistant/components/deconz/strings.json b/homeassistant/components/deconz/strings.json index 632fe832aa8e55..e32ab875c28bb6 100644 --- a/homeassistant/components/deconz/strings.json +++ b/homeassistant/components/deconz/strings.json @@ -116,7 +116,7 @@ "description": "Represents a specific device endpoint in deCONZ." }, "field": { - "name": "Path", + "name": "[%key:common::config_flow::data::path%]", "description": "String representing a full path to deCONZ endpoint (when entity is not specified) or a subpath of the device path for the entity (when entity is specified)." }, "data": { @@ -134,8 +134,8 @@ "description": "Refreshes available devices from deCONZ.", "fields": { "bridgeid": { - "name": "Bridge identifier", - "description": "Unique string for each deCONZ hardware. It can be found as part of the integration name. Useful if you run multiple deCONZ integrations." + "name": "[%key:component::deconz::services::configure::fields::bridgeid::name%]", + "description": "[%key:component::deconz::services::configure::fields::bridgeid::description%]" } } }, @@ -144,8 +144,8 @@ "description": "Cleans up device and entity registry entries orphaned by deCONZ.", "fields": { "bridgeid": { - "name": "Bridge identifier", - "description": "Unique string for each deCONZ hardware. It can be found as part of the integration name. Useful if you run multiple deCONZ integrations." + "name": "[%key:component::deconz::services::configure::fields::bridgeid::name%]", + "description": "[%key:component::deconz::services::configure::fields::bridgeid::description%]" } } } diff --git a/homeassistant/components/demo/strings.json b/homeassistant/components/demo/strings.json index 2dfb3465d68655..d9b896080722e0 100644 --- a/homeassistant/components/demo/strings.json +++ b/homeassistant/components/demo/strings.json @@ -59,7 +59,7 @@ "thermostat_mode": { "name": "Thermostat mode", "state": { - "away": "Away", + "away": "[%key:common::state::not_home%]", "comfort": "Comfort", "eco": "Eco", "sleep": "Sleep" diff --git a/homeassistant/components/derivative/strings.json b/homeassistant/components/derivative/strings.json index 7a4ee9d4fc3540..ef36d46d8b9abf 100644 --- a/homeassistant/components/derivative/strings.json +++ b/homeassistant/components/derivative/strings.json @@ -6,7 +6,7 @@ "title": "Add Derivative sensor", "description": "Create a sensor that estimates the derivative of a sensor.", "data": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "round": "Precision", "source": "Input sensor", "time_window": "Time window", diff --git a/homeassistant/components/devolo_home_control/strings.json b/homeassistant/components/devolo_home_control/strings.json index 84f05b88384568..eeae9aa2e2f7b6 100644 --- a/homeassistant/components/devolo_home_control/strings.json +++ b/homeassistant/components/devolo_home_control/strings.json @@ -18,9 +18,9 @@ }, "zeroconf_confirm": { "data": { - "username": "Email / devolo ID", + "username": "[%key:component::devolo_home_control::config::step::user::data::username%]", "password": "[%key:common::config_flow::data::password%]", - "mydevolo_url": "mydevolo URL" + "mydevolo_url": "[%key:component::devolo_home_control::config::step::user::data::mydevolo_url%]" } } } diff --git a/homeassistant/components/discord/strings.json b/homeassistant/components/discord/strings.json index 07c8fa8bdb54cf..1cd67d3b021933 100644 --- a/homeassistant/components/discord/strings.json +++ b/homeassistant/components/discord/strings.json @@ -8,7 +8,7 @@ } }, "reauth_confirm": { - "description": "Refer to the documentation on getting your Discord bot key.\n\n{url}", + "description": "[%key:component::discord::config::step::user::description%]", "data": { "api_token": "[%key:common::config_flow::data::api_token%]" } diff --git a/homeassistant/components/dlna_dmr/strings.json b/homeassistant/components/dlna_dmr/strings.json index d646f20f7a1024..48f347a0908000 100644 --- a/homeassistant/components/dlna_dmr/strings.json +++ b/homeassistant/components/dlna_dmr/strings.json @@ -34,7 +34,7 @@ }, "error": { "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", - "not_dmr": "Device is not a supported Digital Media Renderer" + "not_dmr": "[%key:component::dlna_dmr::config::abort::not_dmr%]" } }, "options": { diff --git a/homeassistant/components/dnsip/strings.json b/homeassistant/components/dnsip/strings.json index 713cc84efd4b65..d402e27287c616 100644 --- a/homeassistant/components/dnsip/strings.json +++ b/homeassistant/components/dnsip/strings.json @@ -17,8 +17,8 @@ "step": { "init": { "data": { - "resolver": "Resolver for IPV4 lookup", - "resolver_ipv6": "Resolver for IPV6 lookup" + "resolver": "[%key:component::dnsip::config::step::user::data::resolver%]", + "resolver_ipv6": "[%key:component::dnsip::config::step::user::data::resolver_ipv6%]" } } }, diff --git a/homeassistant/components/downloader/strings.json b/homeassistant/components/downloader/strings.json index 49a7388add2e05..c81b9f0ea39f86 100644 --- a/homeassistant/components/downloader/strings.json +++ b/homeassistant/components/downloader/strings.json @@ -5,7 +5,7 @@ "description": "Downloads a file to the download location.", "fields": { "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "The URL of the file to download." }, "subdir": { diff --git a/homeassistant/components/dsmr/strings.json b/homeassistant/components/dsmr/strings.json index 5724ad643feff5..7dc44e47a98c5e 100644 --- a/homeassistant/components/dsmr/strings.json +++ b/homeassistant/components/dsmr/strings.json @@ -18,15 +18,15 @@ "setup_serial": { "data": { "port": "Select device", - "dsmr_version": "Select DSMR version" + "dsmr_version": "[%key:component::dsmr::config::step::setup_network::data::dsmr_version%]" }, - "title": "Device" + "title": "[%key:common::config_flow::data::device%]" }, "setup_serial_manual_path": { "data": { "port": "[%key:common::config_flow::data::usb_path%]" }, - "title": "Path" + "title": "[%key:common::config_flow::data::path%]" } }, "error": { @@ -37,7 +37,7 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", - "cannot_communicate": "Failed to communicate" + "cannot_communicate": "[%key:component::dsmr::config::error::cannot_communicate%]" } }, "entity": { diff --git a/homeassistant/components/dynalite/strings.json b/homeassistant/components/dynalite/strings.json index 512e00237d9852..468cdebf0b1887 100644 --- a/homeassistant/components/dynalite/strings.json +++ b/homeassistant/components/dynalite/strings.json @@ -21,7 +21,7 @@ "description": "Requests Dynalite to report the preset for an area.", "fields": { "host": { - "name": "Host", + "name": "[%key:common::config_flow::data::host%]", "description": "Host gateway IP to send to or all configured gateways if not specified." }, "area": { @@ -39,11 +39,11 @@ "description": "Requests Dynalite to report the level of a specific channel.", "fields": { "host": { - "name": "Host", - "description": "Host gateway IP to send to or all configured gateways if not specified." + "name": "[%key:common::config_flow::data::host%]", + "description": "[%key:component::dynalite::services::request_area_preset::fields::host::description%]" }, "area": { - "name": "Area", + "name": "[%key:component::dynalite::services::request_area_preset::fields::area::name%]", "description": "Area for the requested channel." }, "channel": { diff --git a/homeassistant/components/ecobee/strings.json b/homeassistant/components/ecobee/strings.json index 05ae600d4b733a..fc43fc3000ec52 100644 --- a/homeassistant/components/ecobee/strings.json +++ b/homeassistant/components/ecobee/strings.json @@ -85,7 +85,7 @@ "description": "Ecobee thermostat on which to delete the vacation." }, "vacation_name": { - "name": "Vacation name", + "name": "[%key:component::ecobee::services::create_vacation::fields::vacation_name::name%]", "description": "Name of the vacation to delete." } } @@ -110,10 +110,10 @@ "fields": { "entity_id": { "name": "Entity", - "description": "Name(s) of entities to change." + "description": "[%key:component::ecobee::services::resume_program::fields::entity_id::description%]" }, "fan_min_on_time": { - "name": "Fan minimum on time", + "name": "[%key:component::ecobee::services::create_vacation::fields::fan_min_on_time::name%]", "description": "New value of fan min on time." } } diff --git a/homeassistant/components/eight_sleep/strings.json b/homeassistant/components/eight_sleep/strings.json index bd2b4f11b9d966..b2fb73cc020867 100644 --- a/homeassistant/components/eight_sleep/strings.json +++ b/homeassistant/components/eight_sleep/strings.json @@ -13,7 +13,7 @@ }, "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", - "cannot_connect": "Cannot connect to Eight Sleep cloud: {error}" + "cannot_connect": "[%key:component::eight_sleep::config::error::cannot_connect%]" } }, "services": { diff --git a/homeassistant/components/elkm1/strings.json b/homeassistant/components/elkm1/strings.json index 5ef15827eb9ea8..c854307dd925e7 100644 --- a/homeassistant/components/elkm1/strings.json +++ b/homeassistant/components/elkm1/strings.json @@ -6,7 +6,7 @@ "title": "Connect to Elk-M1 Control", "description": "Choose a discovered system or 'Manual Entry' if no devices have been discovered.", "data": { - "device": "Device" + "device": "[%key:common::config_flow::data::device%]" } }, "manual_connection": { @@ -83,7 +83,7 @@ "fields": { "code": { "name": "Code", - "description": "An code to arm the alarm control panel." + "description": "[%key:component::elkm1::services::alarm_arm_home_instant::fields::code::description%]" } } }, @@ -93,7 +93,7 @@ "fields": { "code": { "name": "Code", - "description": "An code to arm the alarm control panel." + "description": "[%key:component::elkm1::services::alarm_arm_home_instant::fields::code::description%]" } } }, @@ -119,7 +119,7 @@ }, "line2": { "name": "Line 2", - "description": "Up to 16 characters of text (truncated if too long)." + "description": "[%key:component::elkm1::services::alarm_display_message::fields::line1::description%]" } } }, @@ -142,7 +142,7 @@ "description": "Phrase number to speak." }, "prefix": { - "name": "Prefix", + "name": "[%key:component::elkm1::services::set_time::fields::prefix::name%]", "description": "Prefix to identify panel when multiple panels configured." } } @@ -156,8 +156,8 @@ "description": "Word number to speak." }, "prefix": { - "name": "Prefix", - "description": "Prefix to identify panel when multiple panels configured." + "name": "[%key:component::elkm1::services::set_time::fields::prefix::name%]", + "description": "[%key:component::elkm1::services::speak_phrase::fields::prefix::description%]" } } }, diff --git a/homeassistant/components/elmax/strings.json b/homeassistant/components/elmax/strings.json index e8cdbe23a5cced..4bc705adfbefb9 100644 --- a/homeassistant/components/elmax/strings.json +++ b/homeassistant/components/elmax/strings.json @@ -13,7 +13,7 @@ "data": { "panel_name": "Panel Name", "panel_id": "Panel ID", - "panel_pin": "PIN Code" + "panel_pin": "[%key:common::config_flow::data::pin%]" } }, "reauth_confirm": { diff --git a/homeassistant/components/enocean/strings.json b/homeassistant/components/enocean/strings.json index a2aff2a4207e12..97da526185f34e 100644 --- a/homeassistant/components/enocean/strings.json +++ b/homeassistant/components/enocean/strings.json @@ -10,7 +10,7 @@ "manual": { "title": "Enter the path to your ENOcean dongle", "data": { - "path": "USB dongle path" + "path": "[%key:component::enocean::config::step::detect::data::path%]" } } }, diff --git a/homeassistant/components/esphome/strings.json b/homeassistant/components/esphome/strings.json index 2ec1fe1bc41c07..2bbbb229949aec 100644 --- a/homeassistant/components/esphome/strings.json +++ b/homeassistant/components/esphome/strings.json @@ -35,7 +35,7 @@ }, "reauth_confirm": { "data": { - "noise_psk": "Encryption key" + "noise_psk": "[%key:component::esphome::config::step::encryption_key::data::noise_psk%]" }, "description": "The ESPHome device {name} enabled transport encryption or changed the encryption key. Please enter the updated key. You can find it in the ESPHome Dashboard or in your device configuration." }, diff --git a/homeassistant/components/evohome/strings.json b/homeassistant/components/evohome/strings.json index d8214c3aa8bf31..aa38ee170a5db1 100644 --- a/homeassistant/components/evohome/strings.json +++ b/homeassistant/components/evohome/strings.json @@ -5,7 +5,7 @@ "description": "Sets the system mode, either indefinitely, or for a specified period of time, after which it will revert to Auto. Not all systems support all modes.", "fields": { "mode": { - "name": "Mode", + "name": "[%key:common::config_flow::data::mode%]", "description": "Mode to set thermostat." }, "period": { diff --git a/homeassistant/components/facebox/strings.json b/homeassistant/components/facebox/strings.json index 776644c7cfa2f9..1869673b643673 100644 --- a/homeassistant/components/facebox/strings.json +++ b/homeassistant/components/facebox/strings.json @@ -9,7 +9,7 @@ "description": "The facebox entity to teach." }, "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "The name of the face to teach." }, "file_path": { diff --git a/homeassistant/components/flux_led/strings.json b/homeassistant/components/flux_led/strings.json index 7617d56d512194..d1d812cb2102ca 100644 --- a/homeassistant/components/flux_led/strings.json +++ b/homeassistant/components/flux_led/strings.json @@ -114,12 +114,12 @@ "description": "Sets strip zones for Addressable v3 controllers (0xA3).", "fields": { "colors": { - "name": "Colors", + "name": "[%key:component::flux_led::services::set_custom_effect::fields::colors::name%]", "description": "List of colors for each zone (RGB). The length of each zone is the number of pixels per segment divided by the number of colors. (Max 2048 Colors)." }, "speed_pct": { "name": "Speed", - "description": "Effect speed for the custom effect (0-100)." + "description": "[%key:component::flux_led::services::set_custom_effect::fields::speed_pct::description%]" }, "effect": { "name": "Effect", diff --git a/homeassistant/components/forecast_solar/strings.json b/homeassistant/components/forecast_solar/strings.json index a7bc0190f5f7db..7e8c32017ce0ce 100644 --- a/homeassistant/components/forecast_solar/strings.json +++ b/homeassistant/components/forecast_solar/strings.json @@ -8,7 +8,7 @@ "declination": "Declination (0 = Horizontal, 90 = Vertical)", "latitude": "[%key:common::config_flow::data::latitude%]", "longitude": "[%key:common::config_flow::data::longitude%]", - "modules power": "Total Watt peak power of your solar modules", + "modules_power": "Total Watt peak power of your solar modules", "name": "[%key:common::config_flow::data::name%]" } } @@ -23,11 +23,11 @@ "description": "These values allow tweaking the Forecast.Solar result. Please refer to the documentation if a field is unclear.", "data": { "api_key": "Forecast.Solar API Key (optional)", - "azimuth": "Azimuth (360 degrees, 0 = North, 90 = East, 180 = South, 270 = West)", + "azimuth": "[%key:component::forecast_solar::config::step::user::data::azimuth%]", "damping": "Damping factor: adjusts the results in the morning and evening", "inverter_size": "Inverter size (Watt)", - "declination": "Declination (0 = Horizontal, 90 = Vertical)", - "modules power": "Total Watt peak power of your solar modules" + "declination": "[%key:component::forecast_solar::config::step::user::data::declination%]", + "modules power": "[%key:component::forecast_solar::config::step::user::data::modules_power%]" } } } diff --git a/homeassistant/components/fritz/strings.json b/homeassistant/components/fritz/strings.json index dd845fc2a1b54e..7cbb10a236b21c 100644 --- a/homeassistant/components/fritz/strings.json +++ b/homeassistant/components/fritz/strings.json @@ -19,7 +19,7 @@ } }, "user": { - "title": "Set up FRITZ!Box Tools", + "title": "[%key:component::fritz::config::step::confirm::title%]", "description": "Set up FRITZ!Box Tools to control your FRITZ!Box.\nMinimum needed: username, password.", "data": { "host": "[%key:common::config_flow::data::host%]", @@ -126,7 +126,7 @@ }, "services": { "reconnect": { - "name": "Reconnect", + "name": "[%key:component::fritz::entity::button::reconnect::name%]", "description": "Reconnects your FRITZ!Box internet connection.", "fields": { "device_id": { @@ -140,7 +140,7 @@ "description": "Reboots your FRITZ!Box.", "fields": { "device_id": { - "name": "Fritz!Box Device", + "name": "[%key:component::fritz::services::reconnect::fields::device_id::name%]", "description": "Select the Fritz!Box to reboot." } } @@ -150,7 +150,7 @@ "description": "Remove FRITZ!Box stale device_tracker entities.", "fields": { "device_id": { - "name": "Fritz!Box Device", + "name": "[%key:component::fritz::services::reconnect::fields::device_id::name%]", "description": "Select the Fritz!Box to check." } } @@ -160,11 +160,11 @@ "description": "Sets a new password for the guest Wi-Fi. The password must be between 8 and 63 characters long. If no additional parameter is set, the password will be auto-generated with a length of 12 characters.", "fields": { "device_id": { - "name": "Fritz!Box Device", - "description": "Select the Fritz!Box to check." + "name": "[%key:component::fritz::services::reconnect::fields::device_id::name%]", + "description": "Select the Fritz!Box to configure." }, "password": { - "name": "Password", + "name": "[%key:common::config_flow::data::password%]", "description": "New password for the guest Wi-Fi." }, "length": { diff --git a/homeassistant/components/fully_kiosk/strings.json b/homeassistant/components/fully_kiosk/strings.json index 2ecac4a57422ea..d61e8a7b7a89f1 100644 --- a/homeassistant/components/fully_kiosk/strings.json +++ b/homeassistant/components/fully_kiosk/strings.json @@ -112,7 +112,7 @@ "description": "Loads a URL on Fully Kiosk Browser.", "fields": { "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "URL to load." } } diff --git a/homeassistant/components/gardena_bluetooth/strings.json b/homeassistant/components/gardena_bluetooth/strings.json index c7a6e9637dffa0..0a9677b1f92e88 100644 --- a/homeassistant/components/gardena_bluetooth/strings.json +++ b/homeassistant/components/gardena_bluetooth/strings.json @@ -38,7 +38,7 @@ }, "switch": { "state": { - "name": "Open" + "name": "[%key:common::state::open%]" } } } diff --git a/homeassistant/components/geniushub/strings.json b/homeassistant/components/geniushub/strings.json index 1c1092ee256dd7..ac057f5c639dc5 100644 --- a/homeassistant/components/geniushub/strings.json +++ b/homeassistant/components/geniushub/strings.json @@ -9,7 +9,7 @@ "description": "The zone's entity_id." }, "mode": { - "name": "Mode", + "name": "[%key:common::config_flow::data::mode%]", "description": "One of: off, timer or footprint." } } @@ -20,7 +20,7 @@ "fields": { "entity_id": { "name": "Entity", - "description": "The zone's entity_id." + "description": "[%key:component::geniushub::services::set_zone_mode::fields::entity_id::description%]" }, "temperature": { "name": "Temperature", @@ -38,7 +38,7 @@ "fields": { "duration": { "name": "Duration", - "description": "The duration of the override. Optional, default 1 hour, maximum 24 hours." + "description": "[%key:component::geniushub::services::set_zone_override::fields::duration::description%]" } } } diff --git a/homeassistant/components/google/strings.json b/homeassistant/components/google/strings.json index 7fa1569992f6d8..b3594f31510d82 100644 --- a/homeassistant/components/google/strings.json +++ b/homeassistant/components/google/strings.json @@ -88,11 +88,11 @@ "fields": { "summary": { "name": "Summary", - "description": "Acts as the title of the event." + "description": "[%key:component::google::services::add_event::fields::summary::description%]" }, "description": { "name": "Description", - "description": "The description of the event. Optional." + "description": "[%key:component::google::services::add_event::fields::description::description%]" }, "start_date_time": { "name": "Start time", @@ -104,18 +104,18 @@ }, "start_date": { "name": "Start date", - "description": "The date the whole day event should start." + "description": "[%key:component::google::services::add_event::fields::start_date::description%]" }, "end_date": { "name": "End date", - "description": "The date the whole day event should end." + "description": "[%key:component::google::services::add_event::fields::end_date::description%]" }, "in": { "name": "In", "description": "Days or weeks that you want to create the event in." }, "location": { - "name": "Location", + "name": "[%key:common::config_flow::data::location%]", "description": "The location of the event. Optional." } } diff --git a/homeassistant/components/google_generative_ai_conversation/strings.json b/homeassistant/components/google_generative_ai_conversation/strings.json index 2df5398222c877..2b1b41a2c283a8 100644 --- a/homeassistant/components/google_generative_ai_conversation/strings.json +++ b/homeassistant/components/google_generative_ai_conversation/strings.json @@ -18,7 +18,7 @@ "init": { "data": { "prompt": "Prompt Template", - "model": "Model", + "model": "[%key:common::generic::model%]", "temperature": "Temperature", "top_p": "Top P", "top_k": "Top K" diff --git a/homeassistant/components/google_mail/strings.json b/homeassistant/components/google_mail/strings.json index 83537c6b1de3c5..2bd70750ff929f 100644 --- a/homeassistant/components/google_mail/strings.json +++ b/homeassistant/components/google_mail/strings.json @@ -68,7 +68,7 @@ "description": "Restrict automatic reply to domain. This only affects GSuite accounts." }, "start": { - "name": "Start", + "name": "[%key:common::action::start%]", "description": "First day of the vacation." }, "end": { diff --git a/homeassistant/components/group/strings.json b/homeassistant/components/group/strings.json index bbf521b06e3968..1c656b46b9e35b 100644 --- a/homeassistant/components/group/strings.json +++ b/homeassistant/components/group/strings.json @@ -23,7 +23,7 @@ "all": "All entities", "entities": "Members", "hide_members": "Hide members", - "name": "Name" + "name": "[%key:common::config_flow::data::name%]" } }, "cover": { @@ -70,9 +70,9 @@ "title": "[%key:component::group::config::step::user::title%]", "data": { "ignore_non_numeric": "Ignore non-numeric", - "entities": "Members", - "hide_members": "Hide members", - "name": "Name", + "entities": "[%key:component::group::config::step::binary_sensor::data::entities%]", + "hide_members": "[%key:component::group::config::step::binary_sensor::data::hide_members%]", + "name": "[%key:common::config_flow::data::name%]", "type": "Type", "round_digits": "Round value to number of decimals", "device_class": "Device class", @@ -172,7 +172,7 @@ }, "state_attributes": { "entity_id": { - "name": "Members" + "name": "[%key:component::group::config::step::binary_sensor::data::entities%]" } } } @@ -205,7 +205,7 @@ "description": "Object ID of this group. This object ID is used as part of the entity ID. Entity ID format: [domain].[object_id]." }, "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "Name of the group." }, "icon": { @@ -235,8 +235,8 @@ "description": "Removes a group.", "fields": { "object_id": { - "name": "Object ID", - "description": "Object ID of this group. This object ID is used as part of the entity ID. Entity ID format: [domain].[object_id]." + "name": "[%key:component::group::services::set::fields::object_id::name%]", + "description": "[%key:component::group::services::set::fields::object_id::description%]" } } } diff --git a/homeassistant/components/growatt_server/strings.json b/homeassistant/components/growatt_server/strings.json index d2c196dbfdd395..f507387e6285e7 100644 --- a/homeassistant/components/growatt_server/strings.json +++ b/homeassistant/components/growatt_server/strings.json @@ -188,10 +188,10 @@ "name": "Grid discharged today" }, "storage_load_consumption_today": { - "name": "Load consumption today" + "name": "[%key:component::growatt_server::entity::sensor::mix_load_consumption_today::name%]" }, "storage_load_consumption_lifetime": { - "name": "Lifetime load consumption" + "name": "[%key:component::growatt_server::entity::sensor::mix_load_consumption_lifetime::name%]" }, "storage_grid_charged_today": { "name": "Grid charged today" @@ -215,7 +215,7 @@ "name": "Charge today" }, "storage_import_from_grid": { - "name": "Import from grid" + "name": "[%key:component::growatt_server::entity::sensor::mix_import_from_grid::name%]" }, "storage_import_from_grid_today": { "name": "Import from grid today" @@ -224,7 +224,7 @@ "name": "Import from grid total" }, "storage_load_consumption": { - "name": "Load consumption" + "name": "[%key:component::growatt_server::entity::sensor::mix_load_consumption::name%]" }, "storage_grid_voltage": { "name": "AC input voltage" @@ -263,7 +263,7 @@ "name": "Energy today" }, "tlx_energy_total": { - "name": "Lifetime energy output" + "name": "[%key:component::growatt_server::entity::sensor::inverter_energy_total::name%]" }, "tlx_energy_total_input_1": { "name": "Lifetime total energy input 1" @@ -272,13 +272,13 @@ "name": "Energy Today Input 1" }, "tlx_voltage_input_1": { - "name": "Input 1 voltage" + "name": "[%key:component::growatt_server::entity::sensor::inverter_voltage_input_1::name%]" }, "tlx_amperage_input_1": { - "name": "Input 1 Amperage" + "name": "[%key:component::growatt_server::entity::sensor::inverter_amperage_input_1::name%]" }, "tlx_wattage_input_1": { - "name": "Input 1 Wattage" + "name": "[%key:component::growatt_server::entity::sensor::inverter_wattage_input_1::name%]" }, "tlx_energy_total_input_2": { "name": "Lifetime total energy input 2" @@ -287,13 +287,13 @@ "name": "Energy Today Input 2" }, "tlx_voltage_input_2": { - "name": "Input 2 voltage" + "name": "[%key:component::growatt_server::entity::sensor::inverter_voltage_input_2::name%]" }, "tlx_amperage_input_2": { - "name": "Input 2 Amperage" + "name": "[%key:component::growatt_server::entity::sensor::inverter_amperage_input_2::name%]" }, "tlx_wattage_input_2": { - "name": "Input 2 Wattage" + "name": "[%key:component::growatt_server::entity::sensor::inverter_wattage_input_2::name%]" }, "tlx_energy_total_input_3": { "name": "Lifetime total energy input 3" @@ -302,13 +302,13 @@ "name": "Energy Today Input 3" }, "tlx_voltage_input_3": { - "name": "Input 3 voltage" + "name": "[%key:component::growatt_server::entity::sensor::inverter_voltage_input_3::name%]" }, "tlx_amperage_input_3": { - "name": "Input 3 Amperage" + "name": "[%key:component::growatt_server::entity::sensor::inverter_amperage_input_3::name%]" }, "tlx_wattage_input_3": { - "name": "Input 3 Wattage" + "name": "[%key:component::growatt_server::entity::sensor::inverter_wattage_input_3::name%]" }, "tlx_energy_total_input_4": { "name": "Lifetime total energy input 4" @@ -329,16 +329,16 @@ "name": "Lifetime total solar energy" }, "tlx_internal_wattage": { - "name": "Internal wattage" + "name": "[%key:component::growatt_server::entity::sensor::inverter_internal_wattage::name%]" }, "tlx_reactive_voltage": { - "name": "Reactive voltage" + "name": "[%key:component::growatt_server::entity::sensor::inverter_reactive_voltage::name%]" }, "tlx_frequency": { - "name": "AC frequency" + "name": "[%key:component::growatt_server::entity::sensor::inverter_frequency::name%]" }, "tlx_current_wattage": { - "name": "Output power" + "name": "[%key:component::growatt_server::entity::sensor::inverter_current_wattage::name%]" }, "tlx_temperature_1": { "name": "Temperature 1" @@ -392,13 +392,13 @@ "name": "Lifetime total battery 2 charged" }, "tlx_export_to_grid_today": { - "name": "Export to grid today" + "name": "[%key:component::growatt_server::entity::sensor::mix_export_to_grid_today::name%]" }, "tlx_export_to_grid_total": { "name": "Lifetime total export to grid" }, "tlx_load_consumption_today": { - "name": "Load consumption today" + "name": "[%key:component::growatt_server::entity::sensor::mix_load_consumption_today::name%]" }, "mix_load_consumption_total": { "name": "Lifetime total load consumption" @@ -419,7 +419,7 @@ "name": "Output Power" }, "total_energy_output": { - "name": "Lifetime energy output" + "name": "[%key:component::growatt_server::entity::sensor::inverter_energy_total::name%]" }, "total_maximum_output": { "name": "Maximum power" diff --git a/homeassistant/components/guardian/strings.json b/homeassistant/components/guardian/strings.json index f416adac027a01..59630e87932d52 100644 --- a/homeassistant/components/guardian/strings.json +++ b/homeassistant/components/guardian/strings.json @@ -52,7 +52,7 @@ "description": "Adds a new paired sensor to the valve controller.", "fields": { "device_id": { - "name": "Valve controller", + "name": "[%key:component::guardian::entity::switch::valve_controller::name%]", "description": "The valve controller to add the sensor to." }, "uid": { @@ -66,12 +66,12 @@ "description": "Removes a paired sensor from the valve controller.", "fields": { "device_id": { - "name": "Valve controller", + "name": "[%key:component::guardian::entity::switch::valve_controller::name%]", "description": "The valve controller to remove the sensor from." }, "uid": { - "name": "UID", - "description": "The UID of the paired sensor." + "name": "[%key:component::guardian::services::pair_sensor::fields::uid::name%]", + "description": "[%key:component::guardian::services::pair_sensor::fields::uid::description%]" } } }, @@ -80,15 +80,15 @@ "description": "Upgrades the device firmware.", "fields": { "device_id": { - "name": "Valve controller", + "name": "[%key:component::guardian::entity::switch::valve_controller::name%]", "description": "The valve controller whose firmware should be upgraded." }, "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "The URL of the server hosting the firmware file." }, "port": { - "name": "Port", + "name": "[%key:common::config_flow::data::port%]", "description": "The port on which the firmware file is served." }, "filename": { diff --git a/homeassistant/components/habitica/strings.json b/homeassistant/components/habitica/strings.json index 8d2fb38517d977..8dacb0e6321c29 100644 --- a/homeassistant/components/habitica/strings.json +++ b/homeassistant/components/habitica/strings.json @@ -11,8 +11,8 @@ "user": { "data": { "url": "[%key:common::config_flow::data::url%]", - "name": "Override for Habitica\u2019s username. Will be used for service calls", - "api_user": "Habitica\u2019s API user ID", + "name": "Override for Habitica’s username. Will be used for service calls", + "api_user": "Habitica’s API user ID", "api_key": "[%key:common::config_flow::data::api_key%]" }, "description": "Connect your Habitica profile to allow monitoring of your user's profile and tasks. Note that api_id and api_key must be gotten from https://habitica.com/user/settings/api" @@ -25,11 +25,11 @@ "description": "Calls Habitica API.", "fields": { "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "Habitica's username to call for." }, "path": { - "name": "Path", + "name": "[%key:common::config_flow::data::path%]", "description": "Items from API URL in form of an array with method attached at the end. Consult https://habitica.com/apidoc/. Example uses https://habitica.com/apidoc/#api-Task-CreateUserTasks." }, "args": { diff --git a/homeassistant/components/harmony/strings.json b/homeassistant/components/harmony/strings.json index 8e2b435483f4e2..9ae22090d7fbdb 100644 --- a/homeassistant/components/harmony/strings.json +++ b/homeassistant/components/harmony/strings.json @@ -10,7 +10,7 @@ } }, "link": { - "title": "Set up Logitech Harmony Hub", + "title": "[%key:component::harmony::config::step::user::title%]", "description": "Do you want to set up {name} ({host})?" } }, diff --git a/homeassistant/components/hassio/strings.json b/homeassistant/components/hassio/strings.json index e954c0cccf61fe..c45d455631bff5 100644 --- a/homeassistant/components/hassio/strings.json +++ b/homeassistant/components/hassio/strings.json @@ -282,11 +282,11 @@ "description": "Creates a full backup.", "fields": { "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "Optional (default = current date and time)." }, "password": { - "name": "Password", + "name": "[%key:common::config_flow::data::password%]", "description": "Password to protect the backup with." }, "compressed": { @@ -294,7 +294,7 @@ "description": "Compresses the backup files." }, "location": { - "name": "Location", + "name": "[%key:common::config_flow::data::location%]", "description": "Name of a backup network storage to host backups." } } diff --git a/homeassistant/components/hdmi_cec/strings.json b/homeassistant/components/hdmi_cec/strings.json index 6efc9ec4272cb7..22715907a99b6f 100644 --- a/homeassistant/components/hdmi_cec/strings.json +++ b/homeassistant/components/hdmi_cec/strings.json @@ -9,7 +9,7 @@ "description": "Select HDMI device.", "fields": { "device": { - "name": "Device", + "name": "[%key:common::config_flow::data::device%]", "description": "Address of device to select. Can be entity_id, physical address or alias from configuration." } } @@ -41,7 +41,7 @@ } }, "standby": { - "name": "Standby", + "name": "[%key:common::state::standby%]", "description": "Standby all devices which supports it." }, "update": { diff --git a/homeassistant/components/heos/strings.json b/homeassistant/components/heos/strings.json index 635fe08cccc4c0..7bd362cf3d7caa 100644 --- a/homeassistant/components/heos/strings.json +++ b/homeassistant/components/heos/strings.json @@ -22,11 +22,11 @@ "description": "Signs the controller in to a HEOS account.", "fields": { "username": { - "name": "Username", + "name": "[%key:common::config_flow::data::username%]", "description": "The username or email of the HEOS account." }, "password": { - "name": "Password", + "name": "[%key:common::config_flow::data::password%]", "description": "The password of the HEOS account." } } diff --git a/homeassistant/components/here_travel_time/strings.json b/homeassistant/components/here_travel_time/strings.json index 2c031dc0a02881..124aa070595909 100644 --- a/homeassistant/components/here_travel_time/strings.json +++ b/homeassistant/components/here_travel_time/strings.json @@ -16,13 +16,13 @@ } }, "origin_coordinates": { - "title": "Choose Origin", + "title": "[%key:component::here_travel_time::config::step::origin_menu::title%]", "data": { "origin": "Origin as GPS coordinates" } }, "origin_entity_id": { - "title": "Choose Origin", + "title": "[%key:component::here_travel_time::config::step::origin_menu::title%]", "data": { "origin_entity_id": "Origin using an entity" } @@ -30,18 +30,18 @@ "destination_menu": { "title": "Choose Destination", "menu_options": { - "destination_coordinates": "Using a map location", - "destination_entity": "Using an entity" + "destination_coordinates": "[%key:component::here_travel_time::config::step::origin_menu::menu_options::origin_coordinates%]", + "destination_entity": "[%key:component::here_travel_time::config::step::origin_menu::menu_options::origin_entity%]" } }, "destination_coordinates": { - "title": "Choose Destination", + "title": "[%key:component::here_travel_time::config::step::destination_menu::title%]", "data": { "destination": "Destination as GPS coordinates" } }, "destination_entity_id": { - "title": "Choose Destination", + "title": "[%key:component::here_travel_time::config::step::destination_menu::title%]", "data": { "destination_entity_id": "Destination using an entity" } diff --git a/homeassistant/components/hive/strings.json b/homeassistant/components/hive/strings.json index 495c5dad1cc133..e2a3e9dc7e1eb1 100644 --- a/homeassistant/components/hive/strings.json +++ b/homeassistant/components/hive/strings.json @@ -25,7 +25,7 @@ "title": "Hive Configuration." }, "reauth": { - "title": "Hive Login", + "title": "[%key:component::hive::config::step::user::title%]", "description": "Re-enter your Hive login information.", "data": { "username": "[%key:common::config_flow::data::username%]", @@ -82,7 +82,7 @@ }, "temperature": { "name": "Temperature", - "description": "Set the target temperature for the boost period." + "description": "[%key:component::hive::services::boost_heating::fields::temperature::description%]" } } }, @@ -109,7 +109,7 @@ "description": "Set the time period for the boost." }, "on_off": { - "name": "Mode", + "name": "[%key:common::config_flow::data::mode%]", "description": "Set the boost function on or off." } } diff --git a/homeassistant/components/home_connect/strings.json b/homeassistant/components/home_connect/strings.json index 41eedbe83a87d8..091f0c182329ab 100644 --- a/homeassistant/components/home_connect/strings.json +++ b/homeassistant/components/home_connect/strings.json @@ -46,23 +46,23 @@ "fields": { "device_id": { "name": "Device ID", - "description": "Id of the device." + "description": "[%key:component::home_connect::services::start_program::fields::device_id::description%]" }, "program": { - "name": "Program", - "description": "Program to select." + "name": "[%key:component::home_connect::services::start_program::fields::program::name%]", + "description": "[%key:component::home_connect::services::start_program::fields::program::description%]" }, "key": { - "name": "Option key", - "description": "Key of the option." + "name": "[%key:component::home_connect::services::start_program::fields::key::name%]", + "description": "[%key:component::home_connect::services::start_program::fields::key::description%]" }, "value": { - "name": "Option value", - "description": "Value of the option." + "name": "[%key:component::home_connect::services::start_program::fields::value::name%]", + "description": "[%key:component::home_connect::services::start_program::fields::value::description%]" }, "unit": { - "name": "Option unit", - "description": "Unit for the option." + "name": "[%key:component::home_connect::services::start_program::fields::unit::name%]", + "description": "[%key:component::home_connect::services::start_program::fields::unit::description%]" } } }, @@ -72,7 +72,7 @@ "fields": { "device_id": { "name": "Device ID", - "description": "Id of the device." + "description": "[%key:component::home_connect::services::start_program::fields::device_id::description%]" } } }, @@ -82,7 +82,7 @@ "fields": { "device_id": { "name": "Device ID", - "description": "Id of the device." + "description": "[%key:component::home_connect::services::start_program::fields::device_id::description%]" } } }, @@ -92,15 +92,15 @@ "fields": { "device_id": { "name": "Device ID", - "description": "Id of the device." + "description": "[%key:component::home_connect::services::start_program::fields::device_id::description%]" }, "key": { "name": "Key", - "description": "Key of the option." + "description": "[%key:component::home_connect::services::start_program::fields::key::description%]" }, "value": { "name": "Value", - "description": "Value of the option." + "description": "[%key:component::home_connect::services::start_program::fields::value::description%]" } } }, @@ -110,15 +110,15 @@ "fields": { "device_id": { "name": "Device ID", - "description": "Id of the device." + "description": "[%key:component::home_connect::services::start_program::fields::device_id::description%]" }, "key": { "name": "Key", - "description": "Key of the option." + "description": "[%key:component::home_connect::services::start_program::fields::key::description%]" }, "value": { "name": "Value", - "description": "Value of the option." + "description": "[%key:component::home_connect::services::start_program::fields::value::description%]" } } }, @@ -128,7 +128,7 @@ "fields": { "device_id": { "name": "Device ID", - "description": "Id of the device." + "description": "[%key:component::home_connect::services::start_program::fields::device_id::description%]" }, "key": { "name": "Key", diff --git a/homeassistant/components/homeassistant/strings.json b/homeassistant/components/homeassistant/strings.json index 57cb5c3eb566de..791b1a2192951b 100644 --- a/homeassistant/components/homeassistant/strings.json +++ b/homeassistant/components/homeassistant/strings.json @@ -64,11 +64,11 @@ "description": "Updates the Home Assistant location.", "fields": { "latitude": { - "name": "Latitude", + "name": "[%key:common::config_flow::data::latitude%]", "description": "Latitude of your location." }, "longitude": { - "name": "Longitude", + "name": "[%key:common::config_flow::data::longitude%]", "description": "Longitude of your location." } } diff --git a/homeassistant/components/homekit_controller/strings.json b/homeassistant/components/homekit_controller/strings.json index 7420ef7f3f9cfa..e47ae0fca84246 100644 --- a/homeassistant/components/homekit_controller/strings.json +++ b/homeassistant/components/homekit_controller/strings.json @@ -7,7 +7,7 @@ "title": "Device selection", "description": "HomeKit Device communicates over the local area network using a secure encrypted connection without a separate HomeKit Controller or iCloud. Select the device you want to pair with:", "data": { - "device": "Device" + "device": "[%key:common::config_flow::data::device%]" } }, "pair": { @@ -74,8 +74,8 @@ "select": { "ecobee_mode": { "state": { - "away": "Away", - "home": "Home", + "away": "[%key:common::state::not_home%]", + "home": "[%key:common::state::home%]", "sleep": "Sleep" } } @@ -96,7 +96,7 @@ "border_router": "Border Router", "child": "Child", "detached": "Detached", - "disabled": "Disabled", + "disabled": "[%key:common::state::disabled%]", "joining": "Joining", "leader": "Leader", "router": "Router" diff --git a/homeassistant/components/homematic/strings.json b/homeassistant/components/homematic/strings.json index 14f723694fca6c..48ebbe5d3457e4 100644 --- a/homeassistant/components/homematic/strings.json +++ b/homeassistant/components/homematic/strings.json @@ -31,7 +31,7 @@ "description": "Name(s) of homematic central to set value." }, "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "Name of the variable to set." }, "value": { @@ -46,23 +46,23 @@ "fields": { "address": { "name": "Address", - "description": "Address of homematic device or BidCoS-RF for virtual remote." + "description": "[%key:component::homematic::services::virtualkey::fields::address::description%]" }, "channel": { "name": "Channel", - "description": "Channel for calling a keypress." + "description": "[%key:component::homematic::services::virtualkey::fields::channel::description%]" }, "param": { - "name": "Param", - "description": "Event to send i.e. PRESS_LONG, PRESS_SHORT." + "name": "[%key:component::homematic::services::virtualkey::fields::param::name%]", + "description": "[%key:component::homematic::services::virtualkey::fields::param::description%]" }, "interface": { "name": "Interface", - "description": "Set an interface value." + "description": "[%key:component::homematic::services::virtualkey::fields::interface::description%]" }, "value": { "name": "Value", - "description": "New value." + "description": "[%key:component::homematic::services::set_variable_value::fields::value::description%]" }, "value_type": { "name": "Value type", @@ -83,7 +83,7 @@ "description": "Select the given interface into install mode." }, "mode": { - "name": "Mode", + "name": "[%key:common::config_flow::data::mode%]", "description": "1= Normal mode / 2= Remove exists old links." }, "time": { diff --git a/homeassistant/components/homematicip_cloud/strings.json b/homeassistant/components/homematicip_cloud/strings.json index 6a20c5f8a54293..3795508d75dcff 100644 --- a/homeassistant/components/homematicip_cloud/strings.json +++ b/homeassistant/components/homematicip_cloud/strings.json @@ -43,15 +43,15 @@ }, "activate_eco_mode_with_period": { "name": "Activate eco more with period", - "description": "Activates eco mode with period.", + "description": "[%key:component::homematicip_cloud::services::activate_eco_mode_with_duration::description%]", "fields": { "endtime": { "name": "Endtime", "description": "The time when the eco mode should automatically be disabled." }, "accesspoint_id": { - "name": "Accesspoint ID", - "description": "The ID of the Homematic IP Access Point." + "name": "[%key:component::homematicip_cloud::services::activate_eco_mode_with_duration::fields::accesspoint_id::name%]", + "description": "[%key:component::homematicip_cloud::services::activate_eco_mode_with_duration::fields::accesspoint_id::description%]" } } }, @@ -60,7 +60,7 @@ "description": "Activates the vacation mode until the given time.", "fields": { "endtime": { - "name": "Endtime", + "name": "[%key:component::homematicip_cloud::services::activate_eco_mode_with_period::fields::endtime::name%]", "description": "The time when the vacation mode should automatically be disabled." }, "temperature": { @@ -68,8 +68,8 @@ "description": "The set temperature during the vacation mode." }, "accesspoint_id": { - "name": "Accesspoint ID", - "description": "The ID of the Homematic IP Access Point." + "name": "[%key:component::homematicip_cloud::services::activate_eco_mode_with_duration::fields::accesspoint_id::name%]", + "description": "[%key:component::homematicip_cloud::services::activate_eco_mode_with_duration::fields::accesspoint_id::description%]" } } }, @@ -78,8 +78,8 @@ "description": "Deactivates the eco mode immediately.", "fields": { "accesspoint_id": { - "name": "Accesspoint ID", - "description": "The ID of the Homematic IP Access Point." + "name": "[%key:component::homematicip_cloud::services::activate_eco_mode_with_duration::fields::accesspoint_id::name%]", + "description": "[%key:component::homematicip_cloud::services::activate_eco_mode_with_duration::fields::accesspoint_id::description%]" } } }, @@ -88,8 +88,8 @@ "description": "Deactivates the vacation mode immediately.", "fields": { "accesspoint_id": { - "name": "Accesspoint ID", - "description": "The ID of the Homematic IP Access Point." + "name": "[%key:component::homematicip_cloud::services::activate_eco_mode_with_duration::fields::accesspoint_id::name%]", + "description": "[%key:component::homematicip_cloud::services::activate_eco_mode_with_duration::fields::accesspoint_id::description%]" } } }, diff --git a/homeassistant/components/huawei_lte/strings.json b/homeassistant/components/huawei_lte/strings.json index 50c57e6db3ec29..41826dc6ae771f 100644 --- a/homeassistant/components/huawei_lte/strings.json +++ b/homeassistant/components/huawei_lte/strings.json @@ -55,7 +55,7 @@ "description": "Clears traffic statistics.", "fields": { "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "URL of router to clear; optional when only one is configured." } } @@ -65,7 +65,7 @@ "description": "Reboots router.", "fields": { "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "URL of router to reboot; optional when only one is configured." } } @@ -75,7 +75,7 @@ "description": "Resumes suspended integration.", "fields": { "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "URL of router to resume integration for; optional when only one is configured." } } @@ -85,7 +85,7 @@ "description": "Suspends integration. Suspending logs the integration out from the router, and stops accessing it. Useful e.g. if accessing the router web interface from another source such as a web browser is temporarily required. Invoke the resume_integration service to resume.\n.", "fields": { "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "URL of router to suspend integration for; optional when only one is configured." } } diff --git a/homeassistant/components/hue/strings.json b/homeassistant/components/hue/strings.json index 2c3f493e2c8599..aef5dba19869ba 100644 --- a/homeassistant/components/hue/strings.json +++ b/homeassistant/components/hue/strings.json @@ -46,10 +46,10 @@ "dim_up": "Dim up", "turn_off": "[%key:common::action::turn_off%]", "turn_on": "[%key:common::action::turn_on%]", - "1": "First button", - "2": "Second button", - "3": "Third button", - "4": "Fourth button", + "1": "[%key:component::hue::device_automation::trigger_subtype::button_1%]", + "2": "[%key:component::hue::device_automation::trigger_subtype::button_2%]", + "3": "[%key:component::hue::device_automation::trigger_subtype::button_3%]", + "4": "[%key:component::hue::device_automation::trigger_subtype::button_4%]", "clock_wise": "Rotation clockwise", "counter_clock_wise": "Rotation counter-clockwise" }, @@ -62,9 +62,9 @@ "initial_press": "\"{subtype}\" pressed initially", "repeat": "\"{subtype}\" held down", "short_release": "\"{subtype}\" released after short press", - "long_release": "\"{subtype}\" released after long press", - "double_short_release": "Both \"{subtype}\" released", - "start": "\"{subtype}\" pressed initially" + "long_release": "[%key:component::hue::device_automation::trigger_type::remote_button_long_release%]", + "double_short_release": "[%key:component::hue::device_automation::trigger_type::remote_double_button_short_press%]", + "start": "[%key:component::hue::device_automation::trigger_type::initial_press%]" } }, "options": { @@ -107,7 +107,7 @@ "description": "Transition duration it takes to bring devices to the state defined in the scene." }, "dynamic": { - "name": "Dynamic", + "name": "[%key:component::hue::services::hue_activate_scene::fields::dynamic::name%]", "description": "Enable dynamic mode of the scene." }, "speed": { diff --git a/homeassistant/components/hunterdouglas_powerview/strings.json b/homeassistant/components/hunterdouglas_powerview/strings.json index 41a16408783138..ec26e423e06e01 100644 --- a/homeassistant/components/hunterdouglas_powerview/strings.json +++ b/homeassistant/components/hunterdouglas_powerview/strings.json @@ -8,7 +8,7 @@ } }, "link": { - "title": "Connect to the PowerView Hub", + "title": "[%key:component::hunterdouglas_powerview::config::step::user::title%]", "description": "Do you want to set up {name} ({host})?" } }, diff --git a/homeassistant/components/hvv_departures/strings.json b/homeassistant/components/hvv_departures/strings.json index 8f9c06f53fbb9b..a9ec58f12ad54f 100644 --- a/homeassistant/components/hvv_departures/strings.json +++ b/homeassistant/components/hvv_departures/strings.json @@ -18,7 +18,7 @@ "station_select": { "title": "Select Station/Address", "data": { - "station": "Station/Address" + "station": "[%key:component::hvv_departures::config::step::station::data::station%]" } } }, diff --git a/homeassistant/components/icloud/strings.json b/homeassistant/components/icloud/strings.json index 9bc7750790f308..96db11d4656f73 100644 --- a/homeassistant/components/icloud/strings.json +++ b/homeassistant/components/icloud/strings.json @@ -60,7 +60,7 @@ "fields": { "account": { "name": "Account", - "description": "Your iCloud account username (email) or account name." + "description": "[%key:component::icloud::services::update::fields::account::description%]" }, "device_name": { "name": "Device name", @@ -74,7 +74,7 @@ "fields": { "account": { "name": "Account", - "description": "Your iCloud account username (email) or account name." + "description": "[%key:component::icloud::services::update::fields::account::description%]" }, "device_name": { "name": "Device name", @@ -96,7 +96,7 @@ "fields": { "account": { "name": "Account", - "description": "Your iCloud account username (email) or account name." + "description": "[%key:component::icloud::services::update::fields::account::description%]" }, "device_name": { "name": "Device name", diff --git a/homeassistant/components/ifttt/strings.json b/homeassistant/components/ifttt/strings.json index e52a0882eb1b0d..5ba0812697f9e3 100644 --- a/homeassistant/components/ifttt/strings.json +++ b/homeassistant/components/ifttt/strings.json @@ -44,11 +44,11 @@ }, "value2": { "name": "Value 2", - "description": "Generic field to send data via the event." + "description": "[%key:component::ifttt::services::trigger::fields::value1::description%]" }, "value3": { "name": "Value 3", - "description": "Generic field to send data via the event." + "description": "[%key:component::ifttt::services::trigger::fields::value1::description%]" } } } diff --git a/homeassistant/components/ihc/strings.json b/homeassistant/components/ihc/strings.json index 3ee45a4f4649ec..af2152a88bb121 100644 --- a/homeassistant/components/ihc/strings.json +++ b/homeassistant/components/ihc/strings.json @@ -23,12 +23,12 @@ "description": "Sets an integer runtime value on the IHC controller.", "fields": { "controller_id": { - "name": "Controller ID", - "description": "If you have multiple controller, this is the index of you controller\nstarting with 0.\n." + "name": "[%key:component::ihc::services::set_runtime_value_bool::fields::controller_id::name%]", + "description": "[%key:component::ihc::services::set_runtime_value_bool::fields::controller_id::description%]" }, "ihc_id": { - "name": "IHC ID", - "description": "The integer IHC resource ID." + "name": "[%key:component::ihc::services::set_runtime_value_bool::fields::ihc_id::name%]", + "description": "[%key:component::ihc::services::set_runtime_value_bool::fields::ihc_id::description%]" }, "value": { "name": "Value", @@ -41,12 +41,12 @@ "description": "Sets a float runtime value on the IHC controller.", "fields": { "controller_id": { - "name": "Controller ID", - "description": "If you have multiple controller, this is the index of you controller\nstarting with 0.\n." + "name": "[%key:component::ihc::services::set_runtime_value_bool::fields::controller_id::name%]", + "description": "[%key:component::ihc::services::set_runtime_value_bool::fields::controller_id::description%]" }, "ihc_id": { - "name": "IHC ID", - "description": "The integer IHC resource ID." + "name": "[%key:component::ihc::services::set_runtime_value_bool::fields::ihc_id::name%]", + "description": "[%key:component::ihc::services::set_runtime_value_bool::fields::ihc_id::description%]" }, "value": { "name": "Value", @@ -59,12 +59,12 @@ "description": "Pulses an input on the IHC controller.", "fields": { "controller_id": { - "name": "Controller ID", - "description": "If you have multiple controller, this is the index of you controller\nstarting with 0.\n." + "name": "[%key:component::ihc::services::set_runtime_value_bool::fields::controller_id::name%]", + "description": "[%key:component::ihc::services::set_runtime_value_bool::fields::controller_id::description%]" }, "ihc_id": { - "name": "IHC ID", - "description": "The integer IHC resource ID." + "name": "[%key:component::ihc::services::set_runtime_value_bool::fields::ihc_id::name%]", + "description": "[%key:component::ihc::services::set_runtime_value_bool::fields::ihc_id::description%]" } } } diff --git a/homeassistant/components/insteon/strings.json b/homeassistant/components/insteon/strings.json index 3ba996adff772e..37cdd5c0343b89 100644 --- a/homeassistant/components/insteon/strings.json +++ b/homeassistant/components/insteon/strings.json @@ -76,7 +76,7 @@ } }, "add_override": { - "description": "Add a device override.", + "description": "[%key:component::insteon::options::step::init::menu_options::add_override%]", "data": { "address": "Device address (i.e. 1a2b3c)", "cat": "Device category (i.e. 0x10)", @@ -101,7 +101,7 @@ "remove_x10": { "description": "Remove an X10 device", "data": { - "address": "Select a device address to remove" + "address": "[%key:component::insteon::options::step::remove_override::data::address%]" } } }, @@ -120,7 +120,7 @@ "description": "All-Link group number." }, "mode": { - "name": "Mode", + "name": "[%key:common::config_flow::data::mode%]", "description": "Linking mode controller - IM is controller responder - IM is responder." } } @@ -131,7 +131,7 @@ "fields": { "group": { "name": "Group", - "description": "All-Link group number." + "description": "[%key:component::insteon::services::add_all_link::fields::group::description%]" } } }, @@ -165,7 +165,7 @@ }, "x10_all_units_off": { "name": "X10 all units off", - "description": "Tells the Insteom Modem (IM) start All-Linking mode. Once the IM is in All-Linking mode, press the link button on the device to complete All-Linking.", + "description": "[%key:component::insteon::services::add_all_link::description%]", "fields": { "housecode": { "name": "Housecode", @@ -178,8 +178,8 @@ "description": "Sends X10 All Lights On command.", "fields": { "housecode": { - "name": "Housecode", - "description": "X10 house code." + "name": "[%key:component::insteon::services::x10_all_units_off::fields::housecode::name%]", + "description": "[%key:component::insteon::services::x10_all_units_off::fields::housecode::description%]" } } }, @@ -188,8 +188,8 @@ "description": "Sends X10 All Lights Off command.", "fields": { "housecode": { - "name": "Housecode", - "description": "X10 house code." + "name": "[%key:component::insteon::services::x10_all_units_off::fields::housecode::name%]", + "description": "[%key:component::insteon::services::x10_all_units_off::fields::housecode::description%]" } } }, @@ -209,7 +209,7 @@ "fields": { "group": { "name": "Group", - "description": "INSTEON group or scene number." + "description": "[%key:component::insteon::services::scene_on::fields::group::description%]" } } }, @@ -219,7 +219,7 @@ "fields": { "entity_id": { "name": "Entity", - "description": "Name of the device to load. Use \"all\" to load the database of all devices." + "description": "[%key:component::insteon::services::load_all_link_database::fields::entity_id::description%]" } } } diff --git a/homeassistant/components/integration/strings.json b/homeassistant/components/integration/strings.json index 3a3940ffc2c4bd..74c2b3ee440641 100644 --- a/homeassistant/components/integration/strings.json +++ b/homeassistant/components/integration/strings.json @@ -7,7 +7,7 @@ "description": "Create a sensor that calculates a Riemann sum to estimate the integral of a sensor.", "data": { "method": "Integration method", - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "round": "Precision", "source": "Input sensor", "unit_prefix": "Metric prefix", diff --git a/homeassistant/components/iperf3/strings.json b/homeassistant/components/iperf3/strings.json index be8535daec67cb..4c6c68b9573735 100644 --- a/homeassistant/components/iperf3/strings.json +++ b/homeassistant/components/iperf3/strings.json @@ -5,7 +5,7 @@ "description": "Immediately executes a speed test with iperf3.", "fields": { "host": { - "name": "Host", + "name": "[%key:common::config_flow::data::host%]", "description": "The host name of the iperf3 server (already configured) to run a test with." } } diff --git a/homeassistant/components/ipp/strings.json b/homeassistant/components/ipp/strings.json index fa7dd9b6bf8a2a..f3ea929c9eccd3 100644 --- a/homeassistant/components/ipp/strings.json +++ b/homeassistant/components/ipp/strings.json @@ -37,7 +37,7 @@ "printer": { "state": { "printing": "Printing", - "idle": "Idle", + "idle": "[%key:common::state::idle%]", "stopped": "Stopped" } } diff --git a/homeassistant/components/isy994/strings.json b/homeassistant/components/isy994/strings.json index 542df60f13fd60..b39bad14d45e5a 100644 --- a/homeassistant/components/isy994/strings.json +++ b/homeassistant/components/isy994/strings.json @@ -36,7 +36,7 @@ "step": { "init": { "title": "ISY Options", - "description": "Set the options for the ISY Integration: \n \u2022 Node Sensor String: Any device or folder that contains 'Node Sensor String' in the name will be treated as a sensor or binary sensor. \n \u2022 Ignore String: Any device with 'Ignore String' in the name will be ignored. \n \u2022 Variable Sensor String: Any variable that contains 'Variable Sensor String' will be added as a sensor. \n \u2022 Restore Light Brightness: If enabled, the previous brightness will be restored when turning on a light instead of the device's built-in On-Level.", + "description": "Set the options for the ISY Integration: \n • Node Sensor String: Any device or folder that contains 'Node Sensor String' in the name will be treated as a sensor or binary sensor. \n • Ignore String: Any device with 'Ignore String' in the name will be ignored. \n • Variable Sensor String: Any variable that contains 'Variable Sensor String' will be added as a sensor. \n • Restore Light Brightness: If enabled, the previous brightness will be restored when turning on a light instead of the device's built-in On-Level.", "data": { "sensor_string": "Node Sensor String", "ignore_string": "Ignore String", @@ -57,7 +57,7 @@ "services": { "send_raw_node_command": { "name": "Send raw node command", - "description": "Set the options for the ISY Integration: \n \u2022 Node Sensor String: Any device or folder that contains 'Node Sensor String' in the name will be treated as a sensor or binary sensor. \n \u2022 Ignore String: Any device with 'Ignore String' in the name will be ignored. \n \u2022 Variable Sensor String: Any variable that contains 'Variable Sensor String' will be added as a sensor. \n \u2022 Restore Light Brightness: If enabled, the previous brightness will be restored when turning on a light instead of the device's built-in On-Level.", + "description": "[%key:component::isy994::options::step::init::description%]", "fields": { "command": { "name": "Command", @@ -102,7 +102,7 @@ "description": "Updates a Z-Wave Device parameter via the ISY. The parameter value will also be returned as a entity extra state attribute with the name \"ZW_#\" where \"#\" is the parameter number.", "fields": { "parameter": { - "name": "Parameter", + "name": "[%key:component::isy994::services::get_zwave_parameter::fields::parameter::name%]", "description": "The parameter number to set on the end device." }, "value": { @@ -134,8 +134,8 @@ "description": "Delete a Z-Wave Lock User Code via the ISY.", "fields": { "user_num": { - "name": "User Number", - "description": "The user slot number on the lock." + "name": "[%key:component::isy994::services::set_zwave_lock_user_code::fields::user_num::name%]", + "description": "[%key:component::isy994::services::set_zwave_lock_user_code::fields::user_num::description%]" } } }, @@ -158,7 +158,7 @@ "description": "The address of the program to control (use either address or name)." }, "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "The name of the program to control (use either address or name)." }, "command": { diff --git a/homeassistant/components/izone/strings.json b/homeassistant/components/izone/strings.json index 3906dcb89fe4fb..707d7d71d34965 100644 --- a/homeassistant/components/izone/strings.json +++ b/homeassistant/components/izone/strings.json @@ -26,8 +26,8 @@ "description": "Sets the airflow maximum percent for a zone.", "fields": { "airflow": { - "name": "Percent", - "description": "Airflow percent." + "name": "[%key:component::izone::services::airflow_min::fields::airflow::name%]", + "description": "[%key:component::izone::services::airflow_min::fields::airflow::description%]" } } } diff --git a/homeassistant/components/jvc_projector/strings.json b/homeassistant/components/jvc_projector/strings.json index 11e2f66f91ea7e..1f85c20fc72222 100644 --- a/homeassistant/components/jvc_projector/strings.json +++ b/homeassistant/components/jvc_projector/strings.json @@ -29,7 +29,7 @@ "error": { "invalid_host": "[%key:common::config_flow::error::invalid_host%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", - "invalid_auth": "Password authentication failed" + "invalid_auth": "[%key:component::jvc_projector::config::step::reauth_confirm::description%]" } } } diff --git a/homeassistant/components/kaleidescape/strings.json b/homeassistant/components/kaleidescape/strings.json index 30c22a8ca0ee11..0cebfd4bf5c110 100644 --- a/homeassistant/components/kaleidescape/strings.json +++ b/homeassistant/components/kaleidescape/strings.json @@ -19,7 +19,7 @@ }, "error": { "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", - "unsupported": "Unsupported device" + "unsupported": "[%key:component::kaleidescape::config::abort::unsupported%]" } }, "entity": { diff --git a/homeassistant/components/kef/strings.json b/homeassistant/components/kef/strings.json index 7307caa6bb328f..e5ffff681627eb 100644 --- a/homeassistant/components/kef/strings.json +++ b/homeassistant/components/kef/strings.json @@ -49,8 +49,8 @@ "description": "Sets the \"Wall mode\" slider of the speaker in dB.", "fields": { "db_value": { - "name": "DB value", - "description": "Value of the slider." + "name": "[%key:component::kef::services::set_desk_db::fields::db_value::name%]", + "description": "[%key:component::kef::services::set_desk_db::fields::db_value::description%]" } } }, @@ -59,8 +59,8 @@ "description": "Sets desk the \"Treble trim\" slider of the speaker in dB.", "fields": { "db_value": { - "name": "DB value", - "description": "Value of the slider." + "name": "[%key:component::kef::services::set_desk_db::fields::db_value::name%]", + "description": "[%key:component::kef::services::set_desk_db::fields::db_value::description%]" } } }, @@ -70,7 +70,7 @@ "fields": { "hz_value": { "name": "Hertz value", - "description": "Value of the slider." + "description": "[%key:component::kef::services::set_desk_db::fields::db_value::description%]" } } }, @@ -79,8 +79,8 @@ "description": "Set the \"Sub out low-pass frequency\" slider of the speaker in Hz.", "fields": { "hz_value": { - "name": "Hertz value", - "description": "Value of the slider." + "name": "[%key:component::kef::services::set_high_hz::fields::hz_value::name%]", + "description": "[%key:component::kef::services::set_desk_db::fields::db_value::description%]" } } }, @@ -89,8 +89,8 @@ "description": "Set the \"Sub gain\" slider of the speaker in dB.", "fields": { "db_value": { - "name": "DB value", - "description": "Value of the slider." + "name": "[%key:component::kef::services::set_desk_db::fields::db_value::name%]", + "description": "[%key:component::kef::services::set_desk_db::fields::db_value::description%]" } } } diff --git a/homeassistant/components/keymitt_ble/strings.json b/homeassistant/components/keymitt_ble/strings.json index 57e7fc68582c8e..ab2d4ad9440686 100644 --- a/homeassistant/components/keymitt_ble/strings.json +++ b/homeassistant/components/keymitt_ble/strings.json @@ -6,7 +6,7 @@ "title": "Set up MicroBot device", "data": { "address": "Device address", - "name": "Name" + "name": "[%key:common::config_flow::data::name%]" } }, "link": { @@ -42,7 +42,7 @@ "description": "Duration in seconds." }, "mode": { - "name": "Mode", + "name": "[%key:common::config_flow::data::mode%]", "description": "Normal | invert | toggle." } } diff --git a/homeassistant/components/knx/strings.json b/homeassistant/components/knx/strings.json index 56ff9018530e3a..1ff008653d4752 100644 --- a/homeassistant/components/knx/strings.json +++ b/homeassistant/components/knx/strings.json @@ -75,7 +75,7 @@ }, "secure_routing_manual": { "title": "Secure routing", - "description": "Please enter your IP secure information.", + "description": "[%key:component::knx::config::step::secure_tunnel_manual::description%]", "data": { "backbone_key": "Backbone key", "sync_latency_tolerance": "Network latency tolerance" @@ -130,7 +130,7 @@ } }, "communication_settings": { - "title": "Communication settings", + "title": "[%key:component::knx::options::step::options_init::menu_options::communication_settings%]", "data": { "state_updater": "State updater", "rate_limit": "Rate limit", @@ -144,9 +144,9 @@ }, "connection_type": { "title": "[%key:component::knx::config::step::connection_type::title%]", - "description": "Please enter the connection type we should use for your KNX connection. \n AUTOMATIC - The integration takes care of the connectivity to your KNX Bus by performing a gateway scan. \n TUNNELING - The integration will connect to your KNX bus via tunneling. \n ROUTING - The integration will connect to your KNX bus via routing.", + "description": "[%key:component::knx::config::step::connection_type::description%]", "data": { - "connection_type": "KNX Connection Type" + "connection_type": "[%key:component::knx::config::step::connection_type::data::connection_type%]" } }, "tunnel": { @@ -259,7 +259,7 @@ "entity": { "sensor": { "individual_address": { - "name": "Individual address" + "name": "[%key:component::knx::config::step::routing::data::individual_address%]" }, "connected_since": { "name": "Connection established" @@ -317,7 +317,7 @@ "description": "Send GroupValueRead requests to the KNX bus. Response can be used from `knx_event` and will be processed in KNX entities.", "fields": { "address": { - "name": "Group address", + "name": "[%key:component::knx::services::send::fields::address::name%]", "description": "Group address(es) to send read request to. Lists will read multiple group addresses." } } @@ -327,7 +327,7 @@ "description": "Add or remove group addresses to knx_event filter for triggering `knx_event`s. Only addresses added with this service can be removed.", "fields": { "address": { - "name": "Group address", + "name": "[%key:component::knx::services::send::fields::address::name%]", "description": "Group address(es) that shall be added or removed. Lists are allowed." }, "type": { @@ -345,7 +345,7 @@ "description": "Adds or remove exposures to KNX bus. Only exposures added with this service can be removed.", "fields": { "address": { - "name": "Group address", + "name": "[%key:component::knx::services::send::fields::address::name%]", "description": "Group address state or attribute updates will be sent to. GroupValueRead requests will be answered. Per address only one exposure can be registered." }, "type": { @@ -358,11 +358,11 @@ }, "attribute": { "name": "Entity attribute", - "description": "Attribute of the entity that shall be sent to the KNX bus. If not set the state will be sent. Eg. for a light the state is eigther \u201con\u201d or \u201coff\u201d - with attribute you can expose its \u201cbrightness\u201d." + "description": "Attribute of the entity that shall be sent to the KNX bus. If not set the state will be sent. Eg. for a light the state is eigther “on” or “off” - with attribute you can expose its “brightness”." }, "default": { "name": "Default value", - "description": "Default value to send to the bus if the state or attribute value is None. Eg. a light with state \u201coff\u201d has no brightness attribute so a default value of 0 could be used. If not set (or None) no value would be sent to the bus and a GroupReadRequest to the address would return the last known value." + "description": "Default value to send to the bus if the state or attribute value is None. Eg. a light with state “off” has no brightness attribute so a default value of 0 could be used. If not set (or None) no value would be sent to the bus and a GroupReadRequest to the address would return the last known value." }, "remove": { "name": "Remove exposure", diff --git a/homeassistant/components/konnected/strings.json b/homeassistant/components/konnected/strings.json index cd08638c775a97..e1a6863a19999f 100644 --- a/homeassistant/components/konnected/strings.json +++ b/homeassistant/components/konnected/strings.json @@ -69,7 +69,7 @@ }, "options_digital": { "title": "Configure Digital Sensor", - "description": "{zone} options", + "description": "[%key:component::konnected::options::step::options_binary::description%]", "data": { "type": "Sensor Type", "name": "[%key:common::config_flow::data::name%]", @@ -103,7 +103,7 @@ "bad_host": "Invalid Override API host URL" }, "abort": { - "not_konn_panel": "Not a recognized Konnected.io device" + "not_konn_panel": "[%key:component::konnected::config::abort::not_konn_panel%]" } } } diff --git a/homeassistant/components/lametric/strings.json b/homeassistant/components/lametric/strings.json index ac06e125b0c302..21d2bdc84bd128 100644 --- a/homeassistant/components/lametric/strings.json +++ b/homeassistant/components/lametric/strings.json @@ -85,7 +85,7 @@ "description": "Displays a chart on a LaMetric device.", "fields": { "device_id": { - "name": "Device", + "name": "[%key:common::config_flow::data::device%]", "description": "The LaMetric device to display the chart on." }, "data": { @@ -207,7 +207,7 @@ }, "priority": { "options": { - "info": "Info", + "info": "[%key:component::lametric::selector::icon_type::options::info%]", "warning": "Warning", "critical": "Critical" } diff --git a/homeassistant/components/lastfm/strings.json b/homeassistant/components/lastfm/strings.json index fe9a4b6453fefd..006fd5ebcc7379 100644 --- a/homeassistant/components/lastfm/strings.json +++ b/homeassistant/components/lastfm/strings.json @@ -24,15 +24,15 @@ "options": { "step": { "init": { - "description": "Fill in other users you want to add.", + "description": "[%key:component::lastfm::config::step::friends::description%]", "data": { - "users": "Last.fm usernames" + "users": "[%key:component::lastfm::config::step::friends::data::users%]" } } }, "error": { "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]", - "invalid_account": "Invalid username", + "invalid_account": "[%key:component::lastfm::config::error::invalid_account%]", "unknown": "[%key:common::config_flow::error::unknown%]" } } diff --git a/homeassistant/components/lcn/strings.json b/homeassistant/components/lcn/strings.json index 267100eaad631d..e441832926b87e 100644 --- a/homeassistant/components/lcn/strings.json +++ b/homeassistant/components/lcn/strings.json @@ -37,11 +37,11 @@ "fields": { "address": { "name": "Address", - "description": "Module address." + "description": "[%key:component::lcn::services::output_abs::fields::address::description%]" }, "output": { - "name": "Output", - "description": "Output port." + "name": "[%key:component::lcn::services::output_abs::fields::output::name%]", + "description": "[%key:component::lcn::services::output_abs::fields::output::description%]" }, "brightness": { "name": "Brightness", @@ -55,15 +55,15 @@ "fields": { "address": { "name": "Address", - "description": "Module address." + "description": "[%key:component::lcn::services::output_abs::fields::address::description%]" }, "output": { - "name": "Output", - "description": "Output port." + "name": "[%key:component::lcn::services::output_abs::fields::output::name%]", + "description": "[%key:component::lcn::services::output_abs::fields::output::description%]" }, "transition": { "name": "Transition", - "description": "Transition time." + "description": "[%key:component::lcn::services::output_abs::fields::transition::description%]" } } }, @@ -73,7 +73,7 @@ "fields": { "address": { "name": "Address", - "description": "Module address." + "description": "[%key:component::lcn::services::output_abs::fields::address::description%]" }, "state": { "name": "State", @@ -87,10 +87,10 @@ "fields": { "address": { "name": "Address", - "description": "Module address." + "description": "[%key:component::lcn::services::output_abs::fields::address::description%]" }, "led": { - "name": "LED", + "name": "[%key:component::lcn::services::led::name%]", "description": "Led." }, "state": { @@ -105,7 +105,7 @@ "fields": { "address": { "name": "Address", - "description": "Module address." + "description": "[%key:component::lcn::services::output_abs::fields::address::description%]" }, "variable": { "name": "Variable", @@ -127,11 +127,11 @@ "fields": { "address": { "name": "Address", - "description": "Module address." + "description": "[%key:component::lcn::services::output_abs::fields::address::description%]" }, "variable": { - "name": "Variable", - "description": "Variable or setpoint name." + "name": "[%key:component::lcn::services::var_abs::fields::variable::name%]", + "description": "[%key:component::lcn::services::var_abs::fields::variable::description%]" } } }, @@ -141,11 +141,11 @@ "fields": { "address": { "name": "Address", - "description": "Module address." + "description": "[%key:component::lcn::services::output_abs::fields::address::description%]" }, "variable": { - "name": "Variable", - "description": "Variable or setpoint name." + "name": "[%key:component::lcn::services::var_abs::fields::variable::name%]", + "description": "[%key:component::lcn::services::var_abs::fields::variable::description%]" }, "value": { "name": "Value", @@ -153,7 +153,7 @@ }, "unit_of_measurement": { "name": "Unit of measurement", - "description": "Unit of value." + "description": "[%key:component::lcn::services::var_abs::fields::unit_of_measurement::description%]" }, "value_reference": { "name": "Reference value", @@ -167,7 +167,7 @@ "fields": { "address": { "name": "Address", - "description": "Module address." + "description": "[%key:component::lcn::services::output_abs::fields::address::description%]" }, "setpoint": { "name": "Setpoint", @@ -185,7 +185,7 @@ "fields": { "address": { "name": "Address", - "description": "Module address." + "description": "[%key:component::lcn::services::output_abs::fields::address::description%]" }, "keys": { "name": "Keys", @@ -211,7 +211,7 @@ "fields": { "address": { "name": "Address", - "description": "Module address." + "description": "[%key:component::lcn::services::output_abs::fields::address::description%]" }, "table": { "name": "Table", @@ -226,7 +226,7 @@ "description": "Lock interval." }, "time_unit": { - "name": "Time unit", + "name": "[%key:component::lcn::services::send_keys::fields::time_unit::name%]", "description": "Time unit of lock interval." } } @@ -237,7 +237,7 @@ "fields": { "address": { "name": "Address", - "description": "Module address." + "description": "[%key:component::lcn::services::output_abs::fields::address::description%]" }, "row": { "name": "Row", @@ -255,10 +255,10 @@ "fields": { "address": { "name": "Address", - "description": "Module address." + "description": "[%key:component::lcn::services::output_abs::fields::address::description%]" }, "pck": { - "name": "PCK", + "name": "[%key:component::lcn::services::pck::name%]", "description": "PCK command (without address header)." } } diff --git a/homeassistant/components/lifx/strings.json b/homeassistant/components/lifx/strings.json index dfbc0b4e384519..9d155ae32ae15b 100644 --- a/homeassistant/components/lifx/strings.json +++ b/homeassistant/components/lifx/strings.json @@ -10,7 +10,7 @@ }, "pick_device": { "data": { - "device": "Device" + "device": "[%key:common::config_flow::data::device%]" } }, "discovery_confirm": { @@ -88,7 +88,7 @@ "description": "Runs a flash effect by changing to a color and back.", "fields": { "mode": { - "name": "Mode", + "name": "[%key:common::config_flow::data::mode%]", "description": "Decides how colors are changed." }, "brightness": { @@ -142,7 +142,7 @@ "description": "Percentage indicating the maximum saturation of the colors in the loop." }, "period": { - "name": "Period", + "name": "[%key:component::lifx::services::effect_pulse::fields::period::name%]", "description": "Duration between color changes." }, "change": { @@ -155,7 +155,7 @@ }, "power_on": { "name": "Power on", - "description": "Powered off lights are temporarily turned on during the effect." + "description": "[%key:component::lifx::services::effect_pulse::fields::power_on::description%]" } } }, @@ -172,7 +172,7 @@ "description": "Direction the effect will move across the device." }, "theme": { - "name": "Theme", + "name": "[%key:component::lifx::entity::select::theme::name%]", "description": "(Optional) set one of the predefined themes onto the device before starting the effect." }, "power_on": { @@ -191,7 +191,7 @@ }, "power_on": { "name": "Power on", - "description": "Powered off lights will be turned on before starting the effect." + "description": "[%key:component::lifx::services::effect_move::fields::power_on::description%]" } } }, @@ -208,12 +208,12 @@ "description": "List of at least 2 and at most 16 colors as hue (0-360), saturation (0-100), brightness (0-100) and kelvin (1500-900) values to use for this effect. Overrides the theme attribute." }, "theme": { - "name": "Theme", + "name": "[%key:component::lifx::entity::select::theme::name%]", "description": "Predefined color theme to use for the effect. Overridden by the palette attribute." }, "power_on": { "name": "Power on", - "description": "Powered off lights will be turned on before starting the effect." + "description": "[%key:component::lifx::services::effect_move::fields::power_on::description%]" } } }, diff --git a/homeassistant/components/litterrobot/strings.json b/homeassistant/components/litterrobot/strings.json index fe9cc3b528ac61..8436d24902c7a0 100644 --- a/homeassistant/components/litterrobot/strings.json +++ b/homeassistant/components/litterrobot/strings.json @@ -124,7 +124,7 @@ }, "time": { "sleep_mode_start_time": { - "name": "Sleep mode start time" + "name": "[%key:component::litterrobot::entity::sensor::sleep_mode_start_time::name%]" } }, "vacuum": { diff --git a/homeassistant/components/local_ip/strings.json b/homeassistant/components/local_ip/strings.json index 7e214df25924c3..a4d9138d88e563 100644 --- a/homeassistant/components/local_ip/strings.json +++ b/homeassistant/components/local_ip/strings.json @@ -3,7 +3,7 @@ "config": { "step": { "user": { - "title": "Local IP Address", + "title": "[%key:component::local_ip::title%]", "description": "[%key:common::config_flow::description::confirm_setup%]" } }, diff --git a/homeassistant/components/logbook/strings.json b/homeassistant/components/logbook/strings.json index 10ebcc68f64b3e..aad9c122d2377e 100644 --- a/homeassistant/components/logbook/strings.json +++ b/homeassistant/components/logbook/strings.json @@ -5,7 +5,7 @@ "description": "Creates a custom entry in the logbook.", "fields": { "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "Custom name for an entity, can be referenced using an `entity_id`." }, "message": { diff --git a/homeassistant/components/logi_circle/strings.json b/homeassistant/components/logi_circle/strings.json index 9a06fb45ad24ad..4f641238a498e5 100644 --- a/homeassistant/components/logi_circle/strings.json +++ b/homeassistant/components/logi_circle/strings.json @@ -35,7 +35,7 @@ "description": "Name(s) of entities to apply the operation mode to." }, "mode": { - "name": "Mode", + "name": "[%key:common::config_flow::data::mode%]", "description": "Operation mode. Allowed values: LED, RECORDING_MODE." }, "value": { @@ -68,7 +68,7 @@ }, "filename": { "name": "File name", - "description": "Template of a Filename. Variable is entity_id." + "description": "[%key:component::logi_circle::services::livestream_snapshot::fields::filename::description%]" }, "duration": { "name": "Duration", diff --git a/homeassistant/components/lovelace/strings.json b/homeassistant/components/lovelace/strings.json index 64718308325786..d0e456f142bfca 100644 --- a/homeassistant/components/lovelace/strings.json +++ b/homeassistant/components/lovelace/strings.json @@ -2,7 +2,7 @@ "system_health": { "info": { "dashboards": "Dashboards", - "mode": "Mode", + "mode": "[%key:common::config_flow::data::mode%]", "resources": "Resources", "views": "Views" } diff --git a/homeassistant/components/lutron_caseta/strings.json b/homeassistant/components/lutron_caseta/strings.json index bc546321da3fc9..b5ec175d1c9c2a 100644 --- a/homeassistant/components/lutron_caseta/strings.json +++ b/homeassistant/components/lutron_caseta/strings.json @@ -40,9 +40,9 @@ "group_1_button_2": "First Group second button", "group_2_button_1": "Second Group first button", "group_2_button_2": "Second Group second button", - "on": "On", + "on": "[%key:common::state::on%]", "stop": "Stop (favorite)", - "off": "Off", + "off": "[%key:common::state::off%]", "raise": "Raise", "lower": "Lower", "open_all": "Open all", diff --git a/homeassistant/components/matter/strings.json b/homeassistant/components/matter/strings.json index 3d5ae9b6a61e13..61f1ca9180a28b 100644 --- a/homeassistant/components/matter/strings.json +++ b/homeassistant/components/matter/strings.json @@ -57,7 +57,7 @@ "description": "Allows adding one of your devices to another Matter network by opening the commissioning window for this Matter device for 60 seconds.", "fields": { "device_id": { - "name": "Device", + "name": "[%key:common::config_flow::data::device%]", "description": "The Matter device to add to the other Matter network." } } diff --git a/homeassistant/components/mazda/strings.json b/homeassistant/components/mazda/strings.json index 9c881e6324fc4c..a714d1af00f798 100644 --- a/homeassistant/components/mazda/strings.json +++ b/homeassistant/components/mazda/strings.json @@ -31,11 +31,11 @@ "description": "The vehicle to send the GPS location to." }, "latitude": { - "name": "Latitude", + "name": "[%key:common::config_flow::data::latitude%]", "description": "The latitude of the location to send." }, "longitude": { - "name": "Longitude", + "name": "[%key:common::config_flow::data::longitude%]", "description": "The longitude of the location to send." }, "poi_name": { diff --git a/homeassistant/components/meteo_france/strings.json b/homeassistant/components/meteo_france/strings.json index 3ff8d4308a3a25..944f2b32fab883 100644 --- a/homeassistant/components/meteo_france/strings.json +++ b/homeassistant/components/meteo_france/strings.json @@ -10,7 +10,7 @@ "cities": { "description": "Choose your city from the list", "data": { - "city": "City" + "city": "[%key:component::meteo_france::config::step::user::data::city%]" } } }, diff --git a/homeassistant/components/microsoft_face/strings.json b/homeassistant/components/microsoft_face/strings.json index b1008336992f05..4357276a65041d 100644 --- a/homeassistant/components/microsoft_face/strings.json +++ b/homeassistant/components/microsoft_face/strings.json @@ -5,7 +5,7 @@ "description": "Creates a new person group.", "fields": { "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "Name of the group." } } @@ -19,7 +19,7 @@ "description": "Name of the group." }, "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "Name of the person." } } @@ -29,7 +29,7 @@ "description": "Deletes a new person group.", "fields": { "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "Name of the group." } } @@ -43,8 +43,8 @@ "description": "Name of the group." }, "name": { - "name": "Name", - "description": "Name of the person." + "name": "[%key:common::config_flow::data::name%]", + "description": "[%key:component::microsoft_face::services::create_person::fields::name::description%]" } } }, @@ -62,7 +62,7 @@ }, "person": { "name": "Person", - "description": "Name of the person." + "description": "[%key:component::microsoft_face::services::create_person::fields::name::description%]" } } }, diff --git a/homeassistant/components/min_max/strings.json b/homeassistant/components/min_max/strings.json index ce18a4d153f014..e73fac97bb7e26 100644 --- a/homeassistant/components/min_max/strings.json +++ b/homeassistant/components/min_max/strings.json @@ -3,11 +3,11 @@ "config": { "step": { "user": { - "title": "Combine the state of several sensors", + "title": "[%key:component::min_max::title%]", "description": "Create a sensor that calculates a min, max, mean, median or sum from a list of input sensors.", "data": { "entity_ids": "Input entities", - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "round_digits": "Precision", "type": "Statistic characteristic" }, diff --git a/homeassistant/components/minio/strings.json b/homeassistant/components/minio/strings.json index 21902ad1825b8a..75b8375adb1aee 100644 --- a/homeassistant/components/minio/strings.json +++ b/homeassistant/components/minio/strings.json @@ -23,16 +23,16 @@ "description": "Uploads file to Minio.", "fields": { "bucket": { - "name": "Bucket", - "description": "Bucket to use." + "name": "[%key:component::minio::services::get::fields::bucket::name%]", + "description": "[%key:component::minio::services::get::fields::bucket::description%]" }, "key": { "name": "Key", - "description": "Object key of the file." + "description": "[%key:component::minio::services::get::fields::key::description%]" }, "file_path": { "name": "File path", - "description": "File path on local filesystem." + "description": "[%key:component::minio::services::get::fields::file_path::description%]" } } }, @@ -41,12 +41,12 @@ "description": "Deletes file from Minio.", "fields": { "bucket": { - "name": "Bucket", - "description": "Bucket to use." + "name": "[%key:component::minio::services::get::fields::bucket::name%]", + "description": "[%key:component::minio::services::get::fields::bucket::description%]" }, "key": { "name": "Key", - "description": "Object key of the file." + "description": "[%key:component::minio::services::get::fields::key::description%]" } } } diff --git a/homeassistant/components/mjpeg/strings.json b/homeassistant/components/mjpeg/strings.json index 73e6a150a09feb..0e1e71fd82c6c0 100644 --- a/homeassistant/components/mjpeg/strings.json +++ b/homeassistant/components/mjpeg/strings.json @@ -24,10 +24,10 @@ "step": { "init": { "data": { - "mjpeg_url": "MJPEG URL", + "mjpeg_url": "[%key:component::mjpeg::config::step::user::data::mjpeg_url%]", "name": "[%key:common::config_flow::data::name%]", "password": "[%key:common::config_flow::data::password%]", - "still_image_url": "Still Image URL", + "still_image_url": "[%key:component::mjpeg::config::step::user::data::still_image_url%]", "username": "[%key:common::config_flow::data::username%]", "verify_ssl": "[%key:common::config_flow::data::verify_ssl%]" } diff --git a/homeassistant/components/modbus/strings.json b/homeassistant/components/modbus/strings.json index c9cf755ad13416..61694074d7920f 100644 --- a/homeassistant/components/modbus/strings.json +++ b/homeassistant/components/modbus/strings.json @@ -31,20 +31,20 @@ "description": "Writes to a modbus holding register.", "fields": { "address": { - "name": "Address", + "name": "[%key:component::modbus::services::write_coil::fields::address::name%]", "description": "Address of the holding register to write to." }, "slave": { - "name": "Slave", - "description": "Address of the modbus unit/slave." + "name": "[%key:component::modbus::services::write_coil::fields::slave::name%]", + "description": "[%key:component::modbus::services::write_coil::fields::slave::description%]" }, "value": { "name": "Value", "description": "Value (single value or array) to write." }, "hub": { - "name": "Hub", - "description": "Modbus hub name." + "name": "[%key:component::modbus::services::write_coil::fields::hub::name%]", + "description": "[%key:component::modbus::services::write_coil::fields::hub::description%]" } } }, @@ -53,8 +53,8 @@ "description": "Stops modbus hub.", "fields": { "hub": { - "name": "Hub", - "description": "Modbus hub name." + "name": "[%key:component::modbus::services::write_coil::fields::hub::name%]", + "description": "[%key:component::modbus::services::write_coil::fields::hub::description%]" } } }, @@ -63,8 +63,8 @@ "description": "Restarts modbus hub (if running stop then start).", "fields": { "hub": { - "name": "Hub", - "description": "Modbus hub name." + "name": "[%key:component::modbus::services::write_coil::fields::hub::name%]", + "description": "[%key:component::modbus::services::write_coil::fields::hub::description%]" } } } diff --git a/homeassistant/components/modem_callerid/strings.json b/homeassistant/components/modem_callerid/strings.json index bb6ac1879da9f7..2e18ba3654f83e 100644 --- a/homeassistant/components/modem_callerid/strings.json +++ b/homeassistant/components/modem_callerid/strings.json @@ -9,7 +9,7 @@ } }, "usb_confirm": { - "description": "This is an integration for landline calls using a CX93001 voice modem. This can retrieve caller ID information with an option to reject an incoming call." + "description": "[%key:component::modem_callerid::config::step::user::description%]" } }, "error": { diff --git a/homeassistant/components/modern_forms/strings.json b/homeassistant/components/modern_forms/strings.json index 397d7267bc092e..defe412e96dd83 100644 --- a/homeassistant/components/modern_forms/strings.json +++ b/homeassistant/components/modern_forms/strings.json @@ -41,8 +41,8 @@ "description": "Sets a sleep timer on a Modern Forms fan.", "fields": { "sleep_time": { - "name": "Sleep time", - "description": "Number of minutes to set the timer." + "name": "[%key:component::modern_forms::services::set_light_sleep_timer::fields::sleep_time::name%]", + "description": "[%key:component::modern_forms::services::set_light_sleep_timer::fields::sleep_time::description%]" } } }, diff --git a/homeassistant/components/monoprice/strings.json b/homeassistant/components/monoprice/strings.json index 4ecf4cfee45caa..003531518dc950 100644 --- a/homeassistant/components/monoprice/strings.json +++ b/homeassistant/components/monoprice/strings.json @@ -27,12 +27,12 @@ "init": { "title": "Configure sources", "data": { - "source_1": "Name of source #1", - "source_2": "Name of source #2", - "source_3": "Name of source #3", - "source_4": "Name of source #4", - "source_5": "Name of source #5", - "source_6": "Name of source #6" + "source_1": "[%key:component::monoprice::config::step::user::data::source_1%]", + "source_2": "[%key:component::monoprice::config::step::user::data::source_2%]", + "source_3": "[%key:component::monoprice::config::step::user::data::source_3%]", + "source_4": "[%key:component::monoprice::config::step::user::data::source_4%]", + "source_5": "[%key:component::monoprice::config::step::user::data::source_5%]", + "source_6": "[%key:component::monoprice::config::step::user::data::source_6%]" } } } diff --git a/homeassistant/components/mqtt/strings.json b/homeassistant/components/mqtt/strings.json index ae47b33774d655..f314ddd47d3c4b 100644 --- a/homeassistant/components/mqtt/strings.json +++ b/homeassistant/components/mqtt/strings.json @@ -178,7 +178,7 @@ "description": "Writes all messages on a specific topic into the `mqtt_dump.txt` file in your configuration folder.", "fields": { "topic": { - "name": "Topic", + "name": "[%key:component::mqtt::services::publish::fields::topic::name%]", "description": "Topic to listen to." }, "duration": { diff --git a/homeassistant/components/mysensors/strings.json b/homeassistant/components/mysensors/strings.json index 7e0ff2c99d6e36..30fe5f46d6bdd8 100644 --- a/homeassistant/components/mysensors/strings.json +++ b/homeassistant/components/mysensors/strings.json @@ -29,7 +29,7 @@ "data": { "device": "Serial port", "baud_rate": "baud rate", - "version": "MySensors version", + "version": "[%key:component::mysensors::config::step::gw_tcp::data::version%]", "persistence_file": "Persistence file (leave empty to auto-generate)" } }, @@ -39,8 +39,8 @@ "retain": "MQTT retain", "topic_in_prefix": "Prefix for input topics (topic_in_prefix)", "topic_out_prefix": "Prefix for output topics (topic_out_prefix)", - "version": "MySensors version", - "persistence_file": "Persistence file (leave empty to auto-generate)" + "version": "[%key:component::mysensors::config::step::gw_tcp::data::version%]", + "persistence_file": "[%key:component::mysensors::config::step::gw_serial::data::persistence_file%]" } } }, @@ -67,20 +67,20 @@ "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]", - "invalid_subscribe_topic": "Invalid subscribe topic", - "invalid_publish_topic": "Invalid publish topic", - "duplicate_topic": "Topic already in use", - "same_topic": "Subscribe and publish topics are the same", - "invalid_port": "Invalid port number", - "invalid_persistence_file": "Invalid persistence file", - "duplicate_persistence_file": "Persistence file already in use", + "invalid_subscribe_topic": "[%key:component::mysensors::config::error::invalid_subscribe_topic%]", + "invalid_publish_topic": "[%key:component::mysensors::config::error::invalid_publish_topic%]", + "duplicate_topic": "[%key:component::mysensors::config::error::duplicate_topic%]", + "same_topic": "[%key:component::mysensors::config::error::same_topic%]", + "invalid_port": "[%key:component::mysensors::config::error::invalid_port%]", + "invalid_persistence_file": "[%key:component::mysensors::config::error::invalid_persistence_file%]", + "duplicate_persistence_file": "[%key:component::mysensors::config::error::duplicate_persistence_file%]", "invalid_ip": "Invalid IP address", - "invalid_serial": "Invalid serial port", - "invalid_device": "Invalid device", - "invalid_version": "Invalid MySensors version", + "invalid_serial": "[%key:component::mysensors::config::error::invalid_serial%]", + "invalid_device": "[%key:component::mysensors::config::error::invalid_device%]", + "invalid_version": "[%key:component::mysensors::config::error::invalid_version%]", "mqtt_required": "The MQTT integration is not set up", - "not_a_number": "Please enter a number", - "port_out_of_range": "Port number must be at least 1 and at most 65535", + "not_a_number": "[%key:component::mysensors::config::error::not_a_number%]", + "port_out_of_range": "[%key:component::mysensors::config::error::port_out_of_range%]", "unknown": "[%key:common::config_flow::error::unknown%]" } } diff --git a/homeassistant/components/nest/strings.json b/homeassistant/components/nest/strings.json index b6941f51392ff3..2c2def6b7a38d0 100644 --- a/homeassistant/components/nest/strings.json +++ b/homeassistant/components/nest/strings.json @@ -29,7 +29,7 @@ "title": "Configure Google Cloud", "description": "Visit the [Cloud Console]({url}) to find your Google Cloud Project ID.", "data": { - "cloud_project_id": "Google Cloud Project ID" + "cloud_project_id": "[%key:component::nest::config::step::cloud_project::data::cloud_project_id%]" } }, "reauth_confirm": { @@ -101,8 +101,8 @@ "description": "Unique ID for the trip. Default is auto-generated using a timestamp." }, "structure": { - "name": "Structure", - "description": "Name(s) of structure(s) to change. Defaults to all structures if not specified." + "name": "[%key:component::nest::services::set_away_mode::fields::structure::name%]", + "description": "[%key:component::nest::services::set_away_mode::fields::structure::description%]" } } }, @@ -111,12 +111,12 @@ "description": "Cancels an existing estimated time of arrival window for a Nest structure.", "fields": { "trip_id": { - "name": "Trip ID", + "name": "[%key:component::nest::services::set_eta::fields::trip_id::name%]", "description": "Unique ID for the trip." }, "structure": { - "name": "Structure", - "description": "Name(s) of structure(s) to change. Defaults to all structures if not specified." + "name": "[%key:component::nest::services::set_away_mode::fields::structure::name%]", + "description": "[%key:component::nest::services::set_away_mode::fields::structure::description%]" } } } diff --git a/homeassistant/components/netatmo/strings.json b/homeassistant/components/netatmo/strings.json index 05d0e716ef464e..e9125f33016743 100644 --- a/homeassistant/components/netatmo/strings.json +++ b/homeassistant/components/netatmo/strings.json @@ -41,13 +41,13 @@ "weather_areas": "Weather areas" }, "description": "Configure public weather sensors.", - "title": "Netatmo public weather sensor" + "title": "[%key:component::netatmo::options::step::public_weather::title%]" } } }, "device_automation": { "trigger_subtype": { - "away": "Away", + "away": "[%key:common::state::not_home%]", "schedule": "Schedule", "hg": "Frost guard" }, @@ -83,7 +83,7 @@ "description": "Sets the heating schedule for Netatmo climate device. The schedule name must match a schedule configured at Netatmo.", "fields": { "schedule_name": { - "name": "Schedule", + "name": "[%key:component::netatmo::device_automation::trigger_subtype::schedule%]", "description": "Schedule name." } } diff --git a/homeassistant/components/netgear_lte/strings.json b/homeassistant/components/netgear_lte/strings.json index 9c4c67bddf7ba1..1fd1028299140b 100644 --- a/homeassistant/components/netgear_lte/strings.json +++ b/homeassistant/components/netgear_lte/strings.json @@ -5,7 +5,7 @@ "description": "Deletes messages from the modem inbox.", "fields": { "host": { - "name": "Host", + "name": "[%key:common::config_flow::data::host%]", "description": "The modem that should have a message deleted." }, "sms_id": { @@ -19,7 +19,7 @@ "description": "Sets options on the modem.", "fields": { "host": { - "name": "Host", + "name": "[%key:common::config_flow::data::host%]", "description": "The modem to set options on." }, "failover": { @@ -37,7 +37,7 @@ "description": "Asks the modem to establish the LTE connection.", "fields": { "host": { - "name": "Host", + "name": "[%key:common::config_flow::data::host%]", "description": "The modem that should connect." } } @@ -47,7 +47,7 @@ "description": "Asks the modem to close the LTE connection.", "fields": { "host": { - "name": "Host", + "name": "[%key:common::config_flow::data::host%]", "description": "The modem that should disconnect." } } diff --git a/homeassistant/components/nibe_heatpump/strings.json b/homeassistant/components/nibe_heatpump/strings.json index a863b9596b11e7..6fa421e0855a6c 100644 --- a/homeassistant/components/nibe_heatpump/strings.json +++ b/homeassistant/components/nibe_heatpump/strings.json @@ -22,7 +22,7 @@ "nibegw": { "description": "Before attempting to configure the integration, verify that:\n - The NibeGW unit is connected to a heat pump.\n - The MODBUS40 accessory has been enabled in the heat pump configuration.\n - The pump has not gone into an alarm state about missing MODBUS40 accessory.", "data": { - "model": "Model of Heat Pump", + "model": "[%key:component::nibe_heatpump::config::step::modbus::data::model%]", "ip_address": "Remote address", "remote_read_port": "Remote read port", "remote_write_port": "Remote write port", diff --git a/homeassistant/components/nina/strings.json b/homeassistant/components/nina/strings.json index 23a1fb8dfa6b22..e145f5ea8caea9 100644 --- a/homeassistant/components/nina/strings.json +++ b/homeassistant/components/nina/strings.json @@ -29,19 +29,19 @@ "init": { "title": "Options", "data": { - "_a_to_d": "City/county (A-D)", - "_e_to_h": "City/county (E-H)", - "_i_to_l": "City/county (I-L)", - "_m_to_q": "City/county (M-Q)", - "_r_to_u": "City/county (R-U)", - "_v_to_z": "City/county (V-Z)", - "slots": "Maximum warnings per city/county", - "headline_filter": "Blacklist regex to filter warning headlines" + "_a_to_d": "[%key:component::nina::config::step::user::data::_a_to_d%]", + "_e_to_h": "[%key:component::nina::config::step::user::data::_e_to_h%]", + "_i_to_l": "[%key:component::nina::config::step::user::data::_i_to_l%]", + "_m_to_q": "[%key:component::nina::config::step::user::data::_m_to_q%]", + "_r_to_u": "[%key:component::nina::config::step::user::data::_r_to_u%]", + "_v_to_z": "[%key:component::nina::config::step::user::data::_v_to_z%]", + "slots": "[%key:component::nina::config::step::user::data::slots%]", + "headline_filter": "[%key:component::nina::config::step::user::data::headline_filter%]" } } }, "error": { - "no_selection": "Please select at least one city/county", + "no_selection": "[%key:component::nina::config::error::no_selection%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "unknown": "[%key:common::config_flow::error::unknown%]" } diff --git a/homeassistant/components/nissan_leaf/strings.json b/homeassistant/components/nissan_leaf/strings.json index 4dae6cb898b784..d733e39a0fc99b 100644 --- a/homeassistant/components/nissan_leaf/strings.json +++ b/homeassistant/components/nissan_leaf/strings.json @@ -15,8 +15,8 @@ "description": "Fetches the last state of the vehicle of all your accounts, requesting an update from of the state from the car if possible.\n.", "fields": { "vin": { - "name": "VIN", - "description": "The vehicle identification number (VIN) of the vehicle, 17 characters\n." + "name": "[%key:component::nissan_leaf::services::start_charge::fields::vin::name%]", + "description": "[%key:component::nissan_leaf::services::start_charge::fields::vin::description%]" } } } diff --git a/homeassistant/components/nx584/strings.json b/homeassistant/components/nx584/strings.json index 11f94e7a72c538..b3d0381527810d 100644 --- a/homeassistant/components/nx584/strings.json +++ b/homeassistant/components/nx584/strings.json @@ -15,7 +15,7 @@ "description": "Un-Bypasses a zone.", "fields": { "zone": { - "name": "Zone", + "name": "[%key:component::nx584::services::bypass_zone::fields::zone::name%]", "description": "The number of the zone to be un-bypassed." } } diff --git a/homeassistant/components/ombi/strings.json b/homeassistant/components/ombi/strings.json index 70a3767c889e97..2cf18248ab834c 100644 --- a/homeassistant/components/ombi/strings.json +++ b/homeassistant/components/ombi/strings.json @@ -5,7 +5,7 @@ "description": "Searches for a movie and requests the first result.", "fields": { "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "Search parameter." } } @@ -15,8 +15,8 @@ "description": "Searches for a TV show and requests the first result.", "fields": { "name": { - "name": "Name", - "description": "Search parameter." + "name": "[%key:common::config_flow::data::name%]", + "description": "[%key:component::ombi::services::submit_movie_request::fields::name::description%]" }, "season": { "name": "Season", @@ -29,8 +29,8 @@ "description": "Searches for a music album and requests the first result.", "fields": { "name": { - "name": "Name", - "description": "Search parameter." + "name": "[%key:common::config_flow::data::name%]", + "description": "[%key:component::ombi::services::submit_movie_request::fields::name::description%]" } } } diff --git a/homeassistant/components/onewire/strings.json b/homeassistant/components/onewire/strings.json index 2a7bd307ff880f..f58731a2377acc 100644 --- a/homeassistant/components/onewire/strings.json +++ b/homeassistant/components/onewire/strings.json @@ -251,7 +251,7 @@ "device_selection": { "data": { "clear_device_options": "Clear all device configurations", - "device_selection": "Select devices to configure" + "device_selection": "[%key:component::onewire::options::error::device_not_selected%]" }, "description": "Select what configuration steps to process", "title": "OneWire Device Options" diff --git a/homeassistant/components/opentherm_gw/strings.json b/homeassistant/components/opentherm_gw/strings.json index d23fe1c09246d4..a5b8395b56bd7f 100644 --- a/homeassistant/components/opentherm_gw/strings.json +++ b/homeassistant/components/opentherm_gw/strings.json @@ -44,8 +44,8 @@ "description": "Sets the central heating override option on the gateway. When overriding the control setpoint (via a set_control_setpoint service call with a value other than 0), the gateway automatically enables the central heating override to start heating. This service can then be used to control the central heating override status. To return control of the central heating to the thermostat, call the set_control_setpoint service with temperature value 0. You will only need this if you are writing your own software thermostat.\n.", "fields": { "gateway_id": { - "name": "Gateway ID", - "description": "The gateway_id of the OpenTherm Gateway." + "name": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::name%]", + "description": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::description%]" }, "ch_override": { "name": "Central heating override", @@ -58,8 +58,8 @@ "description": "Sets the clock and day of the week on the connected thermostat.", "fields": { "gateway_id": { - "name": "Gateway ID", - "description": "The gateway_id of the OpenTherm Gateway." + "name": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::name%]", + "description": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::description%]" }, "date": { "name": "Date", @@ -76,8 +76,8 @@ "description": "Sets the central heating control setpoint override on the gateway. You will only need this if you are writing your own software thermostat.\n.", "fields": { "gateway_id": { - "name": "Gateway ID", - "description": "The gateway_id of the OpenTherm Gateway." + "name": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::name%]", + "description": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::description%]" }, "temperature": { "name": "Temperature", @@ -90,8 +90,8 @@ "description": "Sets the domestic hot water enable option on the gateway.", "fields": { "gateway_id": { - "name": "Gateway ID", - "description": "The gateway_id of the OpenTherm Gateway." + "name": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::name%]", + "description": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::description%]" }, "dhw_override": { "name": "Domestic hot water override", @@ -104,8 +104,8 @@ "description": "Sets the domestic hot water setpoint on the gateway.", "fields": { "gateway_id": { - "name": "Gateway ID", - "description": "The gateway_id of the OpenTherm Gateway." + "name": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::name%]", + "description": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::description%]" }, "temperature": { "name": "Temperature", @@ -118,15 +118,15 @@ "description": "Changes the function of the GPIO pins of the gateway.", "fields": { "gateway_id": { - "name": "Gateway ID", - "description": "The gateway_id of the OpenTherm Gateway." + "name": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::name%]", + "description": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::description%]" }, "id": { "name": "ID", "description": "The ID of the GPIO pin." }, "mode": { - "name": "Mode", + "name": "[%key:common::config_flow::data::mode%]", "description": "Mode to set on the GPIO pin. Values 0 through 6 are accepted for both GPIOs, 7 is only accepted for GPIO \"B\". See https://www.home-assistant.io/integrations/opentherm_gw/#gpio-modes for an explanation of the values.\n." } } @@ -136,15 +136,15 @@ "description": "Changes the function of the LEDs of the gateway.", "fields": { "gateway_id": { - "name": "Gateway ID", - "description": "The gateway_id of the OpenTherm Gateway." + "name": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::name%]", + "description": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::description%]" }, "id": { "name": "ID", "description": "The ID of the LED." }, "mode": { - "name": "Mode", + "name": "[%key:common::config_flow::data::mode%]", "description": "The function to assign to the LED. See https://www.home-assistant.io/integrations/opentherm_gw/#led-modes for an explanation of the values.\n." } } @@ -154,8 +154,8 @@ "description": "Overrides the maximum relative modulation level. You will only need this if you are writing your own software thermostat.\n.", "fields": { "gateway_id": { - "name": "Gateway ID", - "description": "The gateway_id of the OpenTherm Gateway." + "name": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::name%]", + "description": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::description%]" }, "level": { "name": "Level", @@ -168,8 +168,8 @@ "description": "Provides an outside temperature to the thermostat. If your thermostat is unable to display an outside temperature and does not support OTC (Outside Temperature Correction), this has no effect.\n.", "fields": { "gateway_id": { - "name": "Gateway ID", - "description": "The gateway_id of the OpenTherm Gateway." + "name": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::name%]", + "description": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::description%]" }, "temperature": { "name": "Temperature", @@ -182,8 +182,8 @@ "description": "Configures the setback temperature to be used with the GPIO away mode function.", "fields": { "gateway_id": { - "name": "Gateway ID", - "description": "The gateway_id of the OpenTherm Gateway." + "name": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::name%]", + "description": "[%key:component::opentherm_gw::services::reset_gateway::fields::gateway_id::description%]" }, "temperature": { "name": "Temperature", diff --git a/homeassistant/components/openweathermap/strings.json b/homeassistant/components/openweathermap/strings.json index 12d5c3e21f6c77..a29a8952434a91 100644 --- a/homeassistant/components/openweathermap/strings.json +++ b/homeassistant/components/openweathermap/strings.json @@ -15,7 +15,7 @@ "latitude": "[%key:common::config_flow::data::latitude%]", "longitude": "[%key:common::config_flow::data::longitude%]", "mode": "[%key:common::config_flow::data::mode%]", - "name": "Name" + "name": "[%key:common::config_flow::data::name%]" }, "description": "To generate API key go to https://openweathermap.org/appid" } diff --git a/homeassistant/components/overkiz/strings.json b/homeassistant/components/overkiz/strings.json index a82284c24af2d6..c4daf32499ac5d 100644 --- a/homeassistant/components/overkiz/strings.json +++ b/homeassistant/components/overkiz/strings.json @@ -47,7 +47,7 @@ }, "fan_mode": { "state": { - "away": "Away", + "away": "[%key:common::state::not_home%]", "bypass_boost": "Bypass boost", "home_boost": "Home boost", "kitchen_boost": "Kitchen boost" diff --git a/homeassistant/components/persistent_notification/strings.json b/homeassistant/components/persistent_notification/strings.json index 6b8ddb46c497be..5f256233149941 100644 --- a/homeassistant/components/persistent_notification/strings.json +++ b/homeassistant/components/persistent_notification/strings.json @@ -23,7 +23,7 @@ "description": "Removes a notification from the **Notifications** panel.", "fields": { "notification_id": { - "name": "Notification ID", + "name": "[%key:component::persistent_notification::services::create::fields::notification_id::name%]", "description": "ID of the notification to be removed." } } diff --git a/homeassistant/components/profiler/strings.json b/homeassistant/components/profiler/strings.json index 7b9f6789c79bc7..b9aae585d9f596 100644 --- a/homeassistant/components/profiler/strings.json +++ b/homeassistant/components/profiler/strings.json @@ -60,7 +60,7 @@ "fields": { "scan_interval": { "name": "Scan interval", - "description": "The number of seconds between logging objects." + "description": "[%key:component::profiler::services::start_log_objects::fields::scan_interval::description%]" }, "max_objects": { "name": "Maximum objects", diff --git a/homeassistant/components/prusalink/strings.json b/homeassistant/components/prusalink/strings.json index 53f5f0153fe2d5..aa992b4874f0b3 100644 --- a/homeassistant/components/prusalink/strings.json +++ b/homeassistant/components/prusalink/strings.json @@ -20,8 +20,8 @@ "printer_state": { "state": { "cancelling": "Cancelling", - "idle": "Idle", - "paused": "Paused", + "idle": "[%key:common::state::idle%]", + "paused": "[%key:common::state::paused%]", "pausing": "Pausing", "printing": "Printing" } diff --git a/homeassistant/components/purpleair/strings.json b/homeassistant/components/purpleair/strings.json index 5e7c61c182053c..ff505010713607 100644 --- a/homeassistant/components/purpleair/strings.json +++ b/homeassistant/components/purpleair/strings.json @@ -93,7 +93,7 @@ } }, "settings": { - "title": "Settings", + "title": "[%key:component::purpleair::options::step::init::menu_options::settings%]", "data": { "show_on_map": "Show configured sensor locations on the map" } diff --git a/homeassistant/components/qnap/strings.json b/homeassistant/components/qnap/strings.json index 26ca5dedd34422..64b3f22293aee4 100644 --- a/homeassistant/components/qnap/strings.json +++ b/homeassistant/components/qnap/strings.json @@ -6,9 +6,9 @@ "description": "This qnap sensor allows getting various statistics from your QNAP NAS.", "data": { "host": "Hostname", - "username": "Username", - "password": "Password", - "port": "Port", + "username": "[%key:common::config_flow::data::username%]", + "password": "[%key:common::config_flow::data::password%]", + "port": "[%key:common::config_flow::data::port%]", "ssl": "Enable SSL", "verify_ssl": "Verify SSL" } diff --git a/homeassistant/components/qvr_pro/strings.json b/homeassistant/components/qvr_pro/strings.json index 6f37bcce85e185..de61d38ffea376 100644 --- a/homeassistant/components/qvr_pro/strings.json +++ b/homeassistant/components/qvr_pro/strings.json @@ -15,7 +15,7 @@ "description": "Stops QVR Pro recording on specified channel.", "fields": { "guid": { - "name": "GUID", + "name": "[%key:component::qvr_pro::services::start_record::fields::guid::name%]", "description": "GUID of the channel to stop recording." } } diff --git a/homeassistant/components/rachio/strings.json b/homeassistant/components/rachio/strings.json index 3d776193432e80..2132cab86823fa 100644 --- a/homeassistant/components/rachio/strings.json +++ b/homeassistant/components/rachio/strings.json @@ -67,7 +67,7 @@ "description": "Resume any paused zone runs or schedules.", "fields": { "devices": { - "name": "Devices", + "name": "[%key:component::rachio::services::pause_watering::fields::devices::name%]", "description": "Name of controllers to resume. Defaults to all controllers on the account if not provided." } } @@ -77,7 +77,7 @@ "description": "Stop any currently running zones or schedules.", "fields": { "devices": { - "name": "Devices", + "name": "[%key:component::rachio::services::pause_watering::fields::devices::name%]", "description": "Name of controllers to stop. Defaults to all controllers on the account if not provided." } } diff --git a/homeassistant/components/rainbird/strings.json b/homeassistant/components/rainbird/strings.json index 9f4d0c2e34dc16..6046189ddc485e 100644 --- a/homeassistant/components/rainbird/strings.json +++ b/homeassistant/components/rainbird/strings.json @@ -21,7 +21,7 @@ "options": { "step": { "init": { - "title": "Configure Rain Bird", + "title": "[%key:component::rainbird::config::step::user::title%]", "data": { "duration": "Default irrigation time in minutes" } diff --git a/homeassistant/components/rainmachine/strings.json b/homeassistant/components/rainmachine/strings.json index 783c876fe627fe..fc48ebce4eb14b 100644 --- a/homeassistant/components/rainmachine/strings.json +++ b/homeassistant/components/rainmachine/strings.json @@ -118,7 +118,7 @@ "description": "Restricts all watering activities from starting for a time period.", "fields": { "device_id": { - "name": "Controller", + "name": "[%key:component::rainmachine::services::pause_watering::fields::device_id::name%]", "description": "The controller whose watering activities should be restricted." }, "duration": { @@ -146,7 +146,7 @@ "description": "Stops all watering activities.", "fields": { "device_id": { - "name": "Controller", + "name": "[%key:component::rainmachine::services::pause_watering::fields::device_id::name%]", "description": "The controller whose watering activities should be stopped." } } @@ -164,7 +164,7 @@ "description": "Unpauses all paused watering activities.", "fields": { "device_id": { - "name": "Controller", + "name": "[%key:component::rainmachine::services::pause_watering::fields::device_id::name%]", "description": "The controller whose watering activities should be unpaused." } } @@ -174,7 +174,7 @@ "description": "Push flow meter data to the RainMachine device.", "fields": { "device_id": { - "name": "Controller", + "name": "[%key:component::rainmachine::services::pause_watering::fields::device_id::name%]", "description": "The controller to send flow meter data to." }, "value": { @@ -192,7 +192,7 @@ "description": "Push weather data from Home Assistant to the RainMachine device.\nLocal Weather Push service should be enabled from Settings > Weather > Developer tab for RainMachine to consider the values being sent. Units must be sent in metric; no conversions are performed by the integraion.\nSee details of RainMachine API Here: https://rainmachine.docs.apiary.io/#reference/weather-services/parserdata/post.", "fields": { "device_id": { - "name": "Controller", + "name": "[%key:component::rainmachine::services::pause_watering::fields::device_id::name%]", "description": "The controller for the weather data to be pushed." }, "timestamp": { @@ -201,15 +201,15 @@ }, "mintemp": { "name": "Min temp", - "description": "Minimum temperature (\u00b0C)." + "description": "Minimum temperature (°C)." }, "maxtemp": { "name": "Max temp", - "description": "Maximum temperature (\u00b0C)." + "description": "Maximum temperature (°C)." }, "temperature": { "name": "Temperature", - "description": "Current temperature (\u00b0C)." + "description": "Current temperature (°C)." }, "wind": { "name": "Wind speed", @@ -217,7 +217,7 @@ }, "solarrad": { "name": "Solar radiation", - "description": "Solar radiation (MJ/m\u00b2/h)." + "description": "Solar radiation (MJ/m²/h)." }, "et": { "name": "Evapotranspiration", @@ -249,7 +249,7 @@ }, "dewpoint": { "name": "Dew point", - "description": "Dew point (\u00b0C)." + "description": "Dew point (°C)." } } }, @@ -258,7 +258,7 @@ "description": "Unrestrict all watering activities.", "fields": { "device_id": { - "name": "Controller", + "name": "[%key:component::rainmachine::services::pause_watering::fields::device_id::name%]", "description": "The controller whose watering activities should be unrestricted." } } diff --git a/homeassistant/components/recorder/strings.json b/homeassistant/components/recorder/strings.json index 17539387a29582..24f0d806edd3a2 100644 --- a/homeassistant/components/recorder/strings.json +++ b/homeassistant/components/recorder/strings.json @@ -46,7 +46,7 @@ "description": "List of glob patterns used to select the entities for which the data is to be removed from the recorder database." }, "keep_days": { - "name": "Days to keep", + "name": "[%key:component::recorder::services::purge::fields::keep_days::name%]", "description": "Number of days to keep the data for rows matching the filter. Starting today, counting backward. A value of `7` means that everything older than a week will be purged. The default of 0 days will remove all matching rows immediately." } } diff --git a/homeassistant/components/remember_the_milk/strings.json b/homeassistant/components/remember_the_milk/strings.json index 15ca4c36da87e6..5590691e245e56 100644 --- a/homeassistant/components/remember_the_milk/strings.json +++ b/homeassistant/components/remember_the_milk/strings.json @@ -5,7 +5,7 @@ "description": "Creates (or update) a new task in your Remember The Milk account. If you want to update a task later on, you have to set an \"id\" when creating the task. Note: Updating a tasks does not support the smart syntax.", "fields": { "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "Name of the new task, you can use the smart syntax here." }, "id": { diff --git a/homeassistant/components/renault/strings.json b/homeassistant/components/renault/strings.json index e0b8cb0cdf03ed..0b0c3d87822292 100644 --- a/homeassistant/components/renault/strings.json +++ b/homeassistant/components/renault/strings.json @@ -66,7 +66,7 @@ }, "device_tracker": { "location": { - "name": "Location" + "name": "[%key:common::config_flow::data::location%]" } }, "select": { @@ -74,7 +74,7 @@ "name": "Charge mode", "state": { "always": "Instant", - "always_charging": "Instant", + "always_charging": "[%key:component::renault::entity::select::charge_mode::state::always%]", "schedule_mode": "Planner" } } @@ -163,7 +163,7 @@ }, "temperature": { "name": "Temperature", - "description": "Target A/C temperature in \u00b0C." + "description": "Target A/C temperature in °C." }, "when": { "name": "When", @@ -177,7 +177,7 @@ "fields": { "vehicle": { "name": "Vehicle", - "description": "The vehicle to send the command to." + "description": "[%key:component::renault::services::ac_start::fields::vehicle::description%]" } } }, @@ -187,7 +187,7 @@ "fields": { "vehicle": { "name": "Vehicle", - "description": "The vehicle to send the command to." + "description": "[%key:component::renault::services::ac_start::fields::vehicle::description%]" }, "schedules": { "name": "Schedules", diff --git a/homeassistant/components/rfxtrx/strings.json b/homeassistant/components/rfxtrx/strings.json index 6c49fb38d6cae5..85ddf559cf51dc 100644 --- a/homeassistant/components/rfxtrx/strings.json +++ b/homeassistant/components/rfxtrx/strings.json @@ -25,13 +25,13 @@ "data": { "device": "Select device" }, - "title": "Device" + "title": "[%key:common::config_flow::data::device%]" }, "setup_serial_manual_path": { "data": { "device": "[%key:common::config_flow::data::usb_path%]" }, - "title": "Path" + "title": "[%key:common::config_flow::data::path%]" } } }, diff --git a/homeassistant/components/roborock/strings.json b/homeassistant/components/roborock/strings.json index 63ebd31b34c305..3b3e6221895895 100644 --- a/homeassistant/components/roborock/strings.json +++ b/homeassistant/components/roborock/strings.json @@ -4,7 +4,7 @@ "user": { "description": "Enter your Roborock email address.", "data": { - "username": "Email" + "username": "[%key:common::config_flow::data::email%]" } }, "code": { @@ -51,14 +51,14 @@ "state": { "starting": "Starting", "charger_disconnected": "Charger disconnected", - "idle": "Idle", + "idle": "[%key:common::state::idle%]", "remote_control_active": "Remote control active", "cleaning": "Cleaning", "returning_home": "Returning home", "manual_mode": "Manual mode", "charging": "Charging", "charging_problem": "Charging problem", - "paused": "Paused", + "paused": "[%key:common::state::paused%]", "spot_cleaning": "Spot cleaning", "error": "Error", "shutting_down": "Shutting down", @@ -134,7 +134,7 @@ "moderate": "Moderate", "high": "High", "intense": "Intense", - "custom": "Custom" + "custom": "[%key:component::roborock::entity::select::mop_mode::state::custom%]" } } }, @@ -156,7 +156,7 @@ "state": { "auto": "Auto", "balanced": "Balanced", - "custom": "Custom", + "custom": "[%key:component::roborock::entity::select::mop_mode::state::custom%]", "gentle": "Gentle", "off": "[%key:common::state::off%]", "max": "Max", @@ -164,7 +164,7 @@ "medium": "Medium", "quiet": "Quiet", "silent": "Silent", - "standard": "Standard", + "standard": "[%key:component::roborock::entity::select::mop_mode::state::standard%]", "turbo": "Turbo" } } diff --git a/homeassistant/components/rtsp_to_webrtc/strings.json b/homeassistant/components/rtsp_to_webrtc/strings.json index 939c30766e278d..e52ab554473fa2 100644 --- a/homeassistant/components/rtsp_to_webrtc/strings.json +++ b/homeassistant/components/rtsp_to_webrtc/strings.json @@ -20,8 +20,8 @@ }, "abort": { "single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]", - "server_failure": "RTSPtoWebRTC server returned an error. Check logs for more information.", - "server_unreachable": "Unable to communicate with RTSPtoWebRTC server. Check logs for more information." + "server_failure": "[%key:component::rtsp_to_webrtc::config::error::server_failure%]", + "server_unreachable": "[%key:component::rtsp_to_webrtc::config::error::server_unreachable%]" } }, "options": { diff --git a/homeassistant/components/sabnzbd/strings.json b/homeassistant/components/sabnzbd/strings.json index 5711656ef690e0..a8e146eeb27333 100644 --- a/homeassistant/components/sabnzbd/strings.json +++ b/homeassistant/components/sabnzbd/strings.json @@ -30,7 +30,7 @@ "description": "Resumes downloads.", "fields": { "api_key": { - "name": "SABnzbd API key", + "name": "[%key:component::sabnzbd::services::pause::fields::api_key::name%]", "description": "The SABnzbd API key to resume downloads." } } @@ -40,7 +40,7 @@ "description": "Sets the download speed limit.", "fields": { "api_key": { - "name": "SABnzbd API key", + "name": "[%key:component::sabnzbd::services::pause::fields::api_key::name%]", "description": "The SABnzbd API key to set speed limit." }, "speed": { diff --git a/homeassistant/components/screenlogic/strings.json b/homeassistant/components/screenlogic/strings.json index 79b633e28b617a..4894bc6437d70d 100644 --- a/homeassistant/components/screenlogic/strings.json +++ b/homeassistant/components/screenlogic/strings.json @@ -14,7 +14,7 @@ } }, "gateway_select": { - "title": "ScreenLogic", + "title": "[%key:component::screenlogic::config::step::gateway_entry::title%]", "description": "The following ScreenLogic gateways were discovered. Please select one to configure, or choose to manually configure a ScreenLogic gateway.", "data": { "selected_gateway": "Gateway" @@ -28,7 +28,7 @@ "options": { "step": { "init": { - "title": "ScreenLogic", + "title": "[%key:component::screenlogic::config::step::gateway_entry::title%]", "description": "Specify settings for {gateway_name}", "data": { "scan_interval": "Seconds between scans" diff --git a/homeassistant/components/sfr_box/strings.json b/homeassistant/components/sfr_box/strings.json index 3fc9691cc12f47..7ea18304164271 100644 --- a/homeassistant/components/sfr_box/strings.json +++ b/homeassistant/components/sfr_box/strings.json @@ -84,7 +84,7 @@ "dsl_training": { "name": "DSL training", "state": { - "idle": "Idle", + "idle": "[%key:common::state::idle%]", "g_994_training": "G.994 Training", "g_992_started": "G.992 Started", "g_922_channel_analysis": "G.922 Channel Analysis", diff --git a/homeassistant/components/shelly/strings.json b/homeassistant/components/shelly/strings.json index 265184e622715f..eeb2c3d3224fc2 100644 --- a/homeassistant/components/shelly/strings.json +++ b/homeassistant/components/shelly/strings.json @@ -76,8 +76,8 @@ "selector": { "ble_scanner_mode": { "options": { - "disabled": "Disabled", - "active": "Active", + "disabled": "[%key:common::state::disabled%]", + "active": "[%key:common::state::active%]", "passive": "Passive" } } diff --git a/homeassistant/components/shopping_list/strings.json b/homeassistant/components/shopping_list/strings.json index 598a2bddfffff7..ddac4713facfda 100644 --- a/homeassistant/components/shopping_list/strings.json +++ b/homeassistant/components/shopping_list/strings.json @@ -3,7 +3,7 @@ "config": { "step": { "user": { - "title": "Shopping List", + "title": "[%key:component::shopping_list::title%]", "description": "Do you want to configure the shopping list?" } }, @@ -17,7 +17,7 @@ "description": "Adds an item to the shopping list.", "fields": { "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "The name of the item to add." } } @@ -27,7 +27,7 @@ "description": "Removes the first item with matching name from the shopping list.", "fields": { "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "The name of the item to remove." } } @@ -37,7 +37,7 @@ "description": "Marks the first item with matching name as completed in the shopping list.", "fields": { "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "The name of the item to mark as completed (without removing)." } } @@ -47,7 +47,7 @@ "description": "Marks the first item with matching name as incomplete in the shopping list.", "fields": { "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "The name of the item to mark as incomplete." } } diff --git a/homeassistant/components/simplisafe/strings.json b/homeassistant/components/simplisafe/strings.json index 4be806ebbbd761..992160350809a5 100644 --- a/homeassistant/components/simplisafe/strings.json +++ b/homeassistant/components/simplisafe/strings.json @@ -57,7 +57,7 @@ "description": "Sets/updates a PIN.", "fields": { "device_id": { - "name": "System", + "name": "[%key:component::simplisafe::services::remove_pin::fields::device_id::name%]", "description": "The system to set the PIN on." }, "label": { @@ -75,7 +75,7 @@ "description": "Sets one or more system properties.", "fields": { "device_id": { - "name": "System", + "name": "[%key:component::simplisafe::services::remove_pin::fields::device_id::name%]", "description": "The system whose properties should be set." }, "alarm_duration": { diff --git a/homeassistant/components/smarttub/strings.json b/homeassistant/components/smarttub/strings.json index c130feaa620b22..974e5fb7d370bf 100644 --- a/homeassistant/components/smarttub/strings.json +++ b/homeassistant/components/smarttub/strings.json @@ -42,7 +42,7 @@ "description": "Updates the secondary filtration settings.", "fields": { "mode": { - "name": "Mode", + "name": "[%key:common::config_flow::data::mode%]", "description": "The secondary filtration mode." } } @@ -62,7 +62,7 @@ "description": "Reset a reminder, and set the next time it will be triggered.", "fields": { "days": { - "name": "Days", + "name": "[%key:component::smarttub::services::snooze_reminder::fields::days::name%]", "description": "The number of days when the next reminder should trigger." } } diff --git a/homeassistant/components/sms/strings.json b/homeassistant/components/sms/strings.json index 6bf8cbcc166c54..c005c241d790f4 100644 --- a/homeassistant/components/sms/strings.json +++ b/homeassistant/components/sms/strings.json @@ -4,7 +4,7 @@ "user": { "title": "Connect to the modem", "data": { - "device": "Device", + "device": "[%key:common::config_flow::data::device%]", "baud_speed": "Baud Speed" } } @@ -20,16 +20,30 @@ }, "entity": { "sensor": { - "bit_error_rate": { "name": "Bit error rate" }, - "cid": { "name": "Cell ID" }, - "lac": { "name": "Local area code" }, - "network_code": { "name": "GSM network code" }, - "network_name": { "name": "Network name" }, - "signal_percent": { "name": "Signal percent" }, + "bit_error_rate": { + "name": "Bit error rate" + }, + "cid": { + "name": "Cell ID" + }, + "lac": { + "name": "Local area code" + }, + "network_code": { + "name": "GSM network code" + }, + "network_name": { + "name": "Network name" + }, + "signal_percent": { + "name": "Signal percent" + }, "signal_strength": { "name": "[%key:component::sensor::entity_component::signal_strength::name%]" }, - "state": { "name": "Network status" } + "state": { + "name": "Network status" + } } } } diff --git a/homeassistant/components/snips/strings.json b/homeassistant/components/snips/strings.json index d6c9f4d53f65b7..724e1a86477266 100644 --- a/homeassistant/components/snips/strings.json +++ b/homeassistant/components/snips/strings.json @@ -16,7 +16,7 @@ "fields": { "site_id": { "name": "Site ID", - "description": "Site to turn sounds on, defaults to all sites." + "description": "[%key:component::snips::services::feedback_off::fields::site_id::description%]" } } }, @@ -47,8 +47,8 @@ "description": "If True, session waits for an open session to end, if False session is dropped if one is running." }, "custom_data": { - "name": "Custom data", - "description": "Custom data that will be included with all messages in this session." + "name": "[%key:component::snips::services::say::fields::custom_data::name%]", + "description": "[%key:component::snips::services::say::fields::custom_data::description%]" }, "intent_filter": { "name": "Intent filter", @@ -56,11 +56,11 @@ }, "site_id": { "name": "Site ID", - "description": "Site to use to start session, defaults to default." + "description": "[%key:component::snips::services::say::fields::site_id::description%]" }, "text": { "name": "Text", - "description": "Text to say." + "description": "[%key:component::snips::services::say::fields::text::description%]" } } } diff --git a/homeassistant/components/snooz/strings.json b/homeassistant/components/snooz/strings.json index 878341f23bc596..bc1e68db02fc6f 100644 --- a/homeassistant/components/snooz/strings.json +++ b/homeassistant/components/snooz/strings.json @@ -44,7 +44,7 @@ "description": "Transitions volume off over time.", "fields": { "duration": { - "name": "Transition duration", + "name": "[%key:component::snooz::services::transition_on::fields::duration::name%]", "description": "Time it takes to turn off." } } diff --git a/homeassistant/components/songpal/strings.json b/homeassistant/components/songpal/strings.json index a4df830f1fe8cd..d6874f94f9515d 100644 --- a/homeassistant/components/songpal/strings.json +++ b/homeassistant/components/songpal/strings.json @@ -25,7 +25,7 @@ "description": "Change sound setting.", "fields": { "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "Name of the setting." }, "value": { diff --git a/homeassistant/components/sonos/strings.json b/homeassistant/components/sonos/strings.json index c5b5136e9700ad..7ce1d727b17f98 100644 --- a/homeassistant/components/sonos/strings.json +++ b/homeassistant/components/sonos/strings.json @@ -41,7 +41,7 @@ "description": "Name of entity that will be restored." }, "with_group": { - "name": "With group", + "name": "[%key:component::sonos::services::snapshot::fields::with_group::name%]", "description": "True or False. Also restore the group layout." } } @@ -75,7 +75,7 @@ "description": "Removes an item from the queue.", "fields": { "queue_position": { - "name": "Queue position", + "name": "[%key:component::sonos::services::play_queue::fields::queue_position::name%]", "description": "Position in the queue to remove." } } diff --git a/homeassistant/components/soundtouch/strings.json b/homeassistant/components/soundtouch/strings.json index 616a4fc5a115fd..7af95aab38c0a3 100644 --- a/homeassistant/components/soundtouch/strings.json +++ b/homeassistant/components/soundtouch/strings.json @@ -52,7 +52,7 @@ "description": "Name of the master entity that is coordinating the multi-room zone. Platform dependent." }, "slaves": { - "name": "Slaves", + "name": "[%key:component::soundtouch::services::create_zone::fields::slaves::name%]", "description": "Name of slaves entities to add to the existing zone." } } @@ -63,10 +63,10 @@ "fields": { "master": { "name": "Master", - "description": "Name of the master entity that is coordinating the multi-room zone. Platform dependent." + "description": "[%key:component::soundtouch::services::add_zone_slave::fields::master::description%]" }, "slaves": { - "name": "Slaves", + "name": "[%key:component::soundtouch::services::create_zone::fields::slaves::name%]", "description": "Name of slaves entities to remove from the existing zone." } } diff --git a/homeassistant/components/spotify/strings.json b/homeassistant/components/spotify/strings.json index caec5b8a288f58..ec2721aba8b077 100644 --- a/homeassistant/components/spotify/strings.json +++ b/homeassistant/components/spotify/strings.json @@ -10,12 +10,14 @@ } }, "abort": { - "authorize_url_timeout": "Timeout generating authorize URL.", + "authorize_url_timeout": "[%key:common::config_flow::abort::oauth2_authorize_url_timeout%]", "missing_configuration": "The Spotify integration is not configured. Please follow the documentation.", "no_url_available": "[%key:common::config_flow::abort::oauth2_no_url_available%]", "reauth_account_mismatch": "The Spotify account authenticated with, does not match the account needed re-authentication." }, - "create_entry": { "default": "Successfully authenticated with Spotify." } + "create_entry": { + "default": "Successfully authenticated with Spotify." + } }, "system_health": { "info": { diff --git a/homeassistant/components/squeezebox/strings.json b/homeassistant/components/squeezebox/strings.json index 13fe16aa28c3d4..87881e3414b6a7 100644 --- a/homeassistant/components/squeezebox/strings.json +++ b/homeassistant/components/squeezebox/strings.json @@ -49,11 +49,11 @@ "fields": { "command": { "name": "Command", - "description": "Command to pass to Logitech Media Server (p0 in the CLI documentation)." + "description": "[%key:component::squeezebox::services::call_method::fields::command::description%]" }, "parameters": { "name": "Parameters", - "description": "Array of additional parameters to pass to Logitech Media Server (p1, ..., pN in the CLI documentation).\n." + "description": "[%key:component::squeezebox::services::call_method::fields::parameters::description%]" } } }, diff --git a/homeassistant/components/starline/strings.json b/homeassistant/components/starline/strings.json index 292ae55da1fff8..4d2c497dc8b6aa 100644 --- a/homeassistant/components/starline/strings.json +++ b/homeassistant/components/starline/strings.json @@ -59,7 +59,7 @@ "fields": { "scan_interval": { "name": "Scan interval", - "description": "Update frequency." + "description": "[%key:component::starline::services::set_scan_interval::fields::scan_interval::description%]" } } } diff --git a/homeassistant/components/starlink/strings.json b/homeassistant/components/starlink/strings.json index 48f84ea7baf5a3..aa89d87b6beeb1 100644 --- a/homeassistant/components/starlink/strings.json +++ b/homeassistant/components/starlink/strings.json @@ -26,7 +26,7 @@ "name": "Heating" }, "power_save_idle": { - "name": "Idle" + "name": "[%key:common::state::idle%]" }, "mast_near_vertical": { "name": "Mast near vertical" @@ -52,7 +52,7 @@ "name": "Azimuth" }, "elevation": { - "name": "Elevation" + "name": "[%key:common::config_flow::data::elevation%]" }, "uplink_throughput": { "name": "Uplink throughput" diff --git a/homeassistant/components/steamist/strings.json b/homeassistant/components/steamist/strings.json index a3cd4879c6a219..8827df6a08a148 100644 --- a/homeassistant/components/steamist/strings.json +++ b/homeassistant/components/steamist/strings.json @@ -10,7 +10,7 @@ }, "pick_device": { "data": { - "device": "Device" + "device": "[%key:common::config_flow::data::device%]" } }, "discovery_confirm": { diff --git a/homeassistant/components/subaru/strings.json b/homeassistant/components/subaru/strings.json index 2ce3c3835a64a7..8474d391141b81 100644 --- a/homeassistant/components/subaru/strings.json +++ b/homeassistant/components/subaru/strings.json @@ -11,21 +11,21 @@ } }, "two_factor": { - "title": "Subaru Starlink Configuration", + "title": "[%key:component::subaru::config::step::user::title%]", "description": "Two factor authentication required", "data": { "contact_method": "Please select a contact method:" } }, "two_factor_validate": { - "title": "Subaru Starlink Configuration", + "title": "[%key:component::subaru::config::step::user::title%]", "description": "Please enter validation code received", "data": { "validation_code": "Validation code" } }, "pin": { - "title": "Subaru Starlink Configuration", + "title": "[%key:component::subaru::config::step::user::title%]", "description": "Please enter your MySubaru PIN\nNOTE: All vehicles in account must have the same PIN", "data": { "pin": "PIN" diff --git a/homeassistant/components/surepetcare/strings.json b/homeassistant/components/surepetcare/strings.json index 6e1ec9643a737b..2d297cc829e507 100644 --- a/homeassistant/components/surepetcare/strings.json +++ b/homeassistant/components/surepetcare/strings.json @@ -41,7 +41,7 @@ "description": "Name of pet." }, "location": { - "name": "Location", + "name": "[%key:common::config_flow::data::location%]", "description": "Pet location (Inside or Outside)." } } diff --git a/homeassistant/components/synology_dsm/strings.json b/homeassistant/components/synology_dsm/strings.json index 24ed1aaf568cb1..f7ae9c9f238b05 100644 --- a/homeassistant/components/synology_dsm/strings.json +++ b/homeassistant/components/synology_dsm/strings.json @@ -183,7 +183,7 @@ "description": "Shutdowns the NAS. This service is deprecated and will be removed in future release. Please use the corresponding button entity.", "fields": { "serial": { - "name": "Serial", + "name": "[%key:component::synology_dsm::services::reboot::fields::serial::name%]", "description": "Serial of the NAS to shutdown; required when multiple NAS are configured." } } diff --git a/homeassistant/components/system_bridge/strings.json b/homeassistant/components/system_bridge/strings.json index e4b2b40637cf4d..c3e1f949152e69 100644 --- a/homeassistant/components/system_bridge/strings.json +++ b/homeassistant/components/system_bridge/strings.json @@ -38,7 +38,7 @@ "description": "The server to talk to." }, "path": { - "name": "Path", + "name": "[%key:common::config_flow::data::path%]", "description": "Path to open." } } @@ -48,11 +48,11 @@ "description": "Opens a URL on the server using the default application.", "fields": { "bridge": { - "name": "Bridge", - "description": "The server to talk to." + "name": "[%key:component::system_bridge::services::open_path::fields::bridge::name%]", + "description": "[%key:component::system_bridge::services::open_path::fields::bridge::description%]" }, "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "URL to open." } } @@ -62,7 +62,7 @@ "description": "Sends a keyboard keypress.", "fields": { "bridge": { - "name": "Bridge", + "name": "[%key:component::system_bridge::services::open_path::fields::bridge::name%]", "description": "The server to send the command to." }, "key": { @@ -76,8 +76,8 @@ "description": "Sends text for the server to type.", "fields": { "bridge": { - "name": "Bridge", - "description": "The server to send the command to." + "name": "[%key:component::system_bridge::services::open_path::fields::bridge::name%]", + "description": "[%key:component::system_bridge::services::send_keypress::fields::bridge::description%]" }, "text": { "name": "Text", diff --git a/homeassistant/components/tankerkoenig/strings.json b/homeassistant/components/tankerkoenig/strings.json index b68359a51760aa..dea370f45b343a 100644 --- a/homeassistant/components/tankerkoenig/strings.json +++ b/homeassistant/components/tankerkoenig/strings.json @@ -38,7 +38,7 @@ "init": { "title": "Tankerkoenig options", "data": { - "stations": "Stations", + "stations": "[%key:component::tankerkoenig::config::step::select_station::data::stations%]", "show_on_map": "Show stations on map" } } diff --git a/homeassistant/components/telegram_bot/strings.json b/homeassistant/components/telegram_bot/strings.json index 8104fdd285e369..eeca235ab444a8 100644 --- a/homeassistant/components/telegram_bot/strings.json +++ b/homeassistant/components/telegram_bot/strings.json @@ -51,7 +51,7 @@ "description": "Sends a photo.", "fields": { "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "Remote path to an image." }, "file": { @@ -63,11 +63,11 @@ "description": "The title of the image." }, "username": { - "name": "Username", + "name": "[%key:common::config_flow::data::username%]", "description": "Username for a URL which require HTTP authentication." }, "password": { - "name": "Password", + "name": "[%key:common::config_flow::data::password%]", "description": "Password (or bearer token) for a URL which require HTTP authentication." }, "authentication": { @@ -79,12 +79,12 @@ "description": "An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default." }, "parse_mode": { - "name": "Parse mode", - "description": "Parser for the message text." + "name": "[%key:component::telegram_bot::services::send_message::fields::parse_mode::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::parse_mode::description%]" }, "disable_notification": { - "name": "Disable notification", - "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + "name": "[%key:component::telegram_bot::services::send_message::fields::disable_notification::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::disable_notification::description%]" }, "verify_ssl": { "name": "Verify SSL", @@ -95,16 +95,16 @@ "description": "Timeout for send photo. Will help with timeout errors (poor internet connection, etc)." }, "keyboard": { - "name": "Keyboard", + "name": "[%key:component::telegram_bot::services::send_message::fields::keyboard::name%]", "description": "List of rows of commands, comma-separated, to make a custom keyboard." }, "inline_keyboard": { - "name": "Inline keyboard", - "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + "name": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::description%]" }, "message_tag": { - "name": "Message tag", - "description": "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}." + "name": "[%key:component::telegram_bot::services::send_message::fields::message_tag::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::message_tag::description%]" } } }, @@ -113,11 +113,11 @@ "description": "Sends a sticker.", "fields": { "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "Remote path to a static .webp or animated .tgs sticker." }, "file": { - "name": "File", + "name": "[%key:component::telegram_bot::services::send_photo::fields::file::name%]", "description": "Local path to a static .webp or animated .tgs sticker." }, "sticker_id": { @@ -125,44 +125,44 @@ "description": "ID of a sticker that exists on telegram servers." }, "username": { - "name": "Username", - "description": "Username for a URL which require HTTP authentication." + "name": "[%key:common::config_flow::data::username%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::username::description%]" }, "password": { - "name": "Password", - "description": "Password (or bearer token) for a URL which require HTTP authentication." + "name": "[%key:common::config_flow::data::password%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::password::description%]" }, "authentication": { - "name": "Authentication method", - "description": "Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`." + "name": "[%key:component::telegram_bot::services::send_photo::fields::authentication::name%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::authentication::description%]" }, "target": { "name": "Target", - "description": "An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default." + "description": "[%key:component::telegram_bot::services::send_photo::fields::target::description%]" }, "disable_notification": { - "name": "Disable notification", - "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + "name": "[%key:component::telegram_bot::services::send_message::fields::disable_notification::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::disable_notification::description%]" }, "verify_ssl": { "name": "Verify SSL", - "description": "Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server." + "description": "[%key:component::telegram_bot::services::send_photo::fields::verify_ssl::description%]" }, "timeout": { "name": "Timeout", "description": "Timeout for send sticker. Will help with timeout errors (poor internet connection, etc)." }, "keyboard": { - "name": "Keyboard", - "description": "List of rows of commands, comma-separated, to make a custom keyboard." + "name": "[%key:component::telegram_bot::services::send_message::fields::keyboard::name%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::keyboard::description%]" }, "inline_keyboard": { - "name": "Inline keyboard", - "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + "name": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::description%]" }, "message_tag": { - "name": "Message tag", - "description": "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}." + "name": "[%key:component::telegram_bot::services::send_message::fields::message_tag::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::message_tag::description%]" } } }, @@ -171,56 +171,56 @@ "description": "Sends an anmiation.", "fields": { "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "Remote path to a GIF or H.264/MPEG-4 AVC video without sound." }, "file": { - "name": "File", + "name": "[%key:component::telegram_bot::services::send_photo::fields::file::name%]", "description": "Local path to a GIF or H.264/MPEG-4 AVC video without sound." }, "caption": { - "name": "Caption", + "name": "[%key:component::telegram_bot::services::send_photo::fields::caption::name%]", "description": "The title of the animation." }, "username": { - "name": "Username", - "description": "Username for a URL which require HTTP authentication." + "name": "[%key:common::config_flow::data::username%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::username::description%]" }, "password": { - "name": "Password", - "description": "Password (or bearer token) for a URL which require HTTP authentication." + "name": "[%key:common::config_flow::data::password%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::password::description%]" }, "authentication": { - "name": "Authentication method", - "description": "Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`." + "name": "[%key:component::telegram_bot::services::send_photo::fields::authentication::name%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::authentication::description%]" }, "target": { "name": "Target", - "description": "An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default." + "description": "[%key:component::telegram_bot::services::send_photo::fields::target::description%]" }, "parse_mode": { "name": "Parse Mode", - "description": "Parser for the message text." + "description": "[%key:component::telegram_bot::services::send_message::fields::parse_mode::description%]" }, "disable_notification": { - "name": "Disable notification", - "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + "name": "[%key:component::telegram_bot::services::send_message::fields::disable_notification::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::disable_notification::description%]" }, "verify_ssl": { "name": "Verify SSL", - "description": "Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server." + "description": "[%key:component::telegram_bot::services::send_photo::fields::verify_ssl::description%]" }, "timeout": { "name": "Timeout", - "description": "Timeout for send sticker. Will help with timeout errors (poor internet connection, etc)." + "description": "[%key:component::telegram_bot::services::send_sticker::fields::timeout::description%]" }, "keyboard": { - "name": "Keyboard", - "description": "List of rows of commands, comma-separated, to make a custom keyboard." + "name": "[%key:component::telegram_bot::services::send_message::fields::keyboard::name%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::keyboard::description%]" }, "inline_keyboard": { - "name": "Inline keyboard", - "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + "name": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::description%]" } } }, @@ -229,60 +229,60 @@ "description": "Sends a video.", "fields": { "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "Remote path to a video." }, "file": { - "name": "File", + "name": "[%key:component::telegram_bot::services::send_photo::fields::file::name%]", "description": "Local path to a video." }, "caption": { - "name": "Caption", + "name": "[%key:component::telegram_bot::services::send_photo::fields::caption::name%]", "description": "The title of the video." }, "username": { - "name": "Username", - "description": "Username for a URL which require HTTP authentication." + "name": "[%key:common::config_flow::data::username%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::username::description%]" }, "password": { - "name": "Password", - "description": "Password (or bearer token) for a URL which require HTTP authentication." + "name": "[%key:common::config_flow::data::password%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::password::description%]" }, "authentication": { - "name": "Authentication method", - "description": "Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`." + "name": "[%key:component::telegram_bot::services::send_photo::fields::authentication::name%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::authentication::description%]" }, "target": { "name": "Target", - "description": "An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default." + "description": "[%key:component::telegram_bot::services::send_photo::fields::target::description%]" }, "parse_mode": { - "name": "Parse mode", - "description": "Parser for the message text." + "name": "[%key:component::telegram_bot::services::send_message::fields::parse_mode::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::parse_mode::description%]" }, "disable_notification": { - "name": "Disable notification", - "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + "name": "[%key:component::telegram_bot::services::send_message::fields::disable_notification::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::disable_notification::description%]" }, "verify_ssl": { "name": "Verify SSL", - "description": "Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server." + "description": "[%key:component::telegram_bot::services::send_photo::fields::verify_ssl::description%]" }, "timeout": { "name": "Timeout", "description": "Timeout for send video. Will help with timeout errors (poor internet connection, etc)." }, "keyboard": { - "name": "Keyboard", - "description": "List of rows of commands, comma-separated, to make a custom keyboard." + "name": "[%key:component::telegram_bot::services::send_message::fields::keyboard::name%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::keyboard::description%]" }, "inline_keyboard": { - "name": "Inline keyboard", - "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + "name": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::description%]" }, "message_tag": { - "name": "Message tag", - "description": "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}." + "name": "[%key:component::telegram_bot::services::send_message::fields::message_tag::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::message_tag::description%]" } } }, @@ -291,56 +291,56 @@ "description": "Sends a voice message.", "fields": { "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "Remote path to a voice message." }, "file": { - "name": "File", + "name": "[%key:component::telegram_bot::services::send_photo::fields::file::name%]", "description": "Local path to a voice message." }, "caption": { - "name": "Caption", + "name": "[%key:component::telegram_bot::services::send_photo::fields::caption::name%]", "description": "The title of the voice message." }, "username": { - "name": "Username", - "description": "Username for a URL which require HTTP authentication." + "name": "[%key:common::config_flow::data::username%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::username::description%]" }, "password": { - "name": "Password", - "description": "Password (or bearer token) for a URL which require HTTP authentication." + "name": "[%key:common::config_flow::data::password%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::password::description%]" }, "authentication": { - "name": "Authentication method", - "description": "Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`." + "name": "[%key:component::telegram_bot::services::send_photo::fields::authentication::name%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::authentication::description%]" }, "target": { "name": "Target", - "description": "An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default." + "description": "[%key:component::telegram_bot::services::send_photo::fields::target::description%]" }, "disable_notification": { - "name": "Disable notification", - "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + "name": "[%key:component::telegram_bot::services::send_message::fields::disable_notification::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::disable_notification::description%]" }, "verify_ssl": { "name": "Verify SSL", - "description": "Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server." + "description": "[%key:component::telegram_bot::services::send_photo::fields::verify_ssl::description%]" }, "timeout": { "name": "Timeout", "description": "Timeout for send voice. Will help with timeout errors (poor internet connection, etc)." }, "keyboard": { - "name": "Keyboard", - "description": "List of rows of commands, comma-separated, to make a custom keyboard." + "name": "[%key:component::telegram_bot::services::send_message::fields::keyboard::name%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::keyboard::description%]" }, "inline_keyboard": { - "name": "Inline keyboard", - "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + "name": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::description%]" }, "message_tag": { - "name": "Message tag", - "description": "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}." + "name": "[%key:component::telegram_bot::services::send_message::fields::message_tag::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::message_tag::description%]" } } }, @@ -349,60 +349,60 @@ "description": "Sends a document.", "fields": { "url": { - "name": "URL", + "name": "[%key:common::config_flow::data::url%]", "description": "Remote path to a document." }, "file": { - "name": "File", + "name": "[%key:component::telegram_bot::services::send_photo::fields::file::name%]", "description": "Local path to a document." }, "caption": { - "name": "Caption", + "name": "[%key:component::telegram_bot::services::send_photo::fields::caption::name%]", "description": "The title of the document." }, "username": { - "name": "Username", - "description": "Username for a URL which require HTTP authentication." + "name": "[%key:common::config_flow::data::username%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::username::description%]" }, "password": { - "name": "Password", - "description": "Password (or bearer token) for a URL which require HTTP authentication." + "name": "[%key:common::config_flow::data::password%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::password::description%]" }, "authentication": { - "name": "Authentication method", - "description": "Define which authentication method to use. Set to `digest` to use HTTP digest authentication, or `bearer_token` for OAuth 2.0 bearer token authentication. Defaults to `basic`." + "name": "[%key:component::telegram_bot::services::send_photo::fields::authentication::name%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::authentication::description%]" }, "target": { "name": "Target", - "description": "An array of pre-authorized chat_ids to send the document to. If not present, first allowed chat_id is the default." + "description": "[%key:component::telegram_bot::services::send_photo::fields::target::description%]" }, "parse_mode": { - "name": "Parse mode", - "description": "Parser for the message text." + "name": "[%key:component::telegram_bot::services::send_message::fields::parse_mode::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::parse_mode::description%]" }, "disable_notification": { - "name": "Disable notification", - "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + "name": "[%key:component::telegram_bot::services::send_message::fields::disable_notification::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::disable_notification::description%]" }, "verify_ssl": { "name": "Verify SSL", - "description": "Enable or disable SSL certificate verification. Set to false if you're downloading the file from a URL and you don't want to validate the SSL certificate of the server." + "description": "[%key:component::telegram_bot::services::send_photo::fields::verify_ssl::description%]" }, "timeout": { "name": "Timeout", "description": "Timeout for send document. Will help with timeout errors (poor internet connection, etc)." }, "keyboard": { - "name": "Keyboard", - "description": "List of rows of commands, comma-separated, to make a custom keyboard." + "name": "[%key:component::telegram_bot::services::send_message::fields::keyboard::name%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::keyboard::description%]" }, "inline_keyboard": { - "name": "Inline keyboard", - "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + "name": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::description%]" }, "message_tag": { - "name": "Message tag", - "description": "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}." + "name": "[%key:component::telegram_bot::services::send_message::fields::message_tag::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::message_tag::description%]" } } }, @@ -411,11 +411,11 @@ "description": "Sends a location.", "fields": { "latitude": { - "name": "Latitude", + "name": "[%key:common::config_flow::data::latitude%]", "description": "The latitude to send." }, "longitude": { - "name": "Longitude", + "name": "[%key:common::config_flow::data::longitude%]", "description": "The longitude to send." }, "target": { @@ -423,24 +423,24 @@ "description": "An array of pre-authorized chat_ids to send the location to. If not present, first allowed chat_id is the default." }, "disable_notification": { - "name": "Disable notification", - "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + "name": "[%key:component::telegram_bot::services::send_message::fields::disable_notification::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::disable_notification::description%]" }, "timeout": { "name": "Timeout", - "description": "Timeout for send photo. Will help with timeout errors (poor internet connection, etc)." + "description": "[%key:component::telegram_bot::services::send_photo::fields::timeout::description%]" }, "keyboard": { - "name": "Keyboard", - "description": "List of rows of commands, comma-separated, to make a custom keyboard." + "name": "[%key:component::telegram_bot::services::send_message::fields::keyboard::name%]", + "description": "[%key:component::telegram_bot::services::send_photo::fields::keyboard::description%]" }, "inline_keyboard": { - "name": "Inline keyboard", - "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + "name": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::description%]" }, "message_tag": { - "name": "Message tag", - "description": "Tag for sent message. In telegram_sent event data: {{trigger.event.data.message_tag}}." + "name": "[%key:component::telegram_bot::services::send_message::fields::message_tag::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::message_tag::description%]" } } }, @@ -450,7 +450,7 @@ "fields": { "target": { "name": "Target", - "description": "An array of pre-authorized chat_ids to send the location to. If not present, first allowed chat_id is the default." + "description": "[%key:component::telegram_bot::services::send_location::fields::target::description%]" }, "question": { "name": "Question", @@ -473,8 +473,8 @@ "description": "Amount of time in seconds the poll will be active after creation, 5-600." }, "disable_notification": { - "name": "Disable notification", - "description": "Sends the message silently. iOS users and Web users will not receive a notification, Android users will receive a notification with no sound." + "name": "[%key:component::telegram_bot::services::send_message::fields::disable_notification::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::disable_notification::description%]" }, "timeout": { "name": "Timeout", @@ -500,19 +500,19 @@ }, "title": { "name": "Title", - "description": "Optional title for your notification. Will be composed as '%title\\n%message'." + "description": "[%key:component::telegram_bot::services::send_message::fields::title::description%]" }, "parse_mode": { - "name": "Parse mode", - "description": "Parser for the message text." + "name": "[%key:component::telegram_bot::services::send_message::fields::parse_mode::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::parse_mode::description%]" }, "disable_web_page_preview": { - "name": "Disable web page preview", - "description": "Disables link previews for links in the message." + "name": "[%key:component::telegram_bot::services::send_message::fields::disable_web_page_preview::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::disable_web_page_preview::description%]" }, "inline_keyboard": { - "name": "Inline keyboard", - "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + "name": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::description%]" } } }, @@ -521,20 +521,20 @@ "description": "Edits the caption of a previously sent message.", "fields": { "message_id": { - "name": "Message ID", - "description": "Id of the message to edit." + "name": "[%key:component::telegram_bot::services::edit_message::fields::message_id::name%]", + "description": "[%key:component::telegram_bot::services::edit_message::fields::message_id::description%]" }, "chat_id": { - "name": "Chat ID", + "name": "[%key:component::telegram_bot::services::edit_message::fields::chat_id::name%]", "description": "The chat_id where to edit the caption." }, "caption": { - "name": "Caption", + "name": "[%key:component::telegram_bot::services::send_photo::fields::caption::name%]", "description": "Message body of the notification." }, "inline_keyboard": { - "name": "Inline keyboard", - "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + "name": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::description%]" } } }, @@ -543,16 +543,16 @@ "description": "Edit the inline keyboard of a previously sent message.", "fields": { "message_id": { - "name": "Message ID", - "description": "Id of the message to edit." + "name": "[%key:component::telegram_bot::services::edit_message::fields::message_id::name%]", + "description": "[%key:component::telegram_bot::services::edit_message::fields::message_id::description%]" }, "chat_id": { - "name": "Chat ID", + "name": "[%key:component::telegram_bot::services::edit_message::fields::chat_id::name%]", "description": "The chat_id where to edit the reply_markup." }, "inline_keyboard": { - "name": "Inline keyboard", - "description": "List of rows of commands, comma-separated, to make a custom inline keyboard with buttons with associated callback data." + "name": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::name%]", + "description": "[%key:component::telegram_bot::services::send_message::fields::inline_keyboard::description%]" } } }, @@ -583,11 +583,11 @@ "description": "Deletes a previously sent message.", "fields": { "message_id": { - "name": "Message ID", + "name": "[%key:component::telegram_bot::services::edit_message::fields::message_id::name%]", "description": "Id of the message to delete." }, "chat_id": { - "name": "Chat ID", + "name": "[%key:component::telegram_bot::services::edit_message::fields::chat_id::name%]", "description": "The chat_id where to delete the message." } } diff --git a/homeassistant/components/threshold/strings.json b/homeassistant/components/threshold/strings.json index 8bfd9fb96b1662..832f3b4f899c1b 100644 --- a/homeassistant/components/threshold/strings.json +++ b/homeassistant/components/threshold/strings.json @@ -9,7 +9,7 @@ "entity_id": "Input sensor", "hysteresis": "Hysteresis", "lower": "Lower limit", - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "upper": "Upper limit" } } diff --git a/homeassistant/components/tile/strings.json b/homeassistant/components/tile/strings.json index da53f79b697f64..504823c4d16841 100644 --- a/homeassistant/components/tile/strings.json +++ b/homeassistant/components/tile/strings.json @@ -26,7 +26,7 @@ "options": { "step": { "init": { - "title": "Configure Tile", + "title": "[%key:component::tile::config::step::user::title%]", "data": { "show_inactive": "Show inactive Tiles" } diff --git a/homeassistant/components/tod/strings.json b/homeassistant/components/tod/strings.json index 41e40525081d3b..bd4a48df915190 100644 --- a/homeassistant/components/tod/strings.json +++ b/homeassistant/components/tod/strings.json @@ -8,7 +8,7 @@ "data": { "after_time": "On time", "before_time": "Off time", - "name": "Name" + "name": "[%key:common::config_flow::data::name%]" } } } diff --git a/homeassistant/components/tplink/strings.json b/homeassistant/components/tplink/strings.json index b5279804d0a3d3..6daa5c9cb1aecd 100644 --- a/homeassistant/components/tplink/strings.json +++ b/homeassistant/components/tplink/strings.json @@ -10,7 +10,7 @@ }, "pick_device": { "data": { - "device": "Device" + "device": "[%key:common::config_flow::data::device%]" } }, "discovery_confirm": { @@ -74,7 +74,7 @@ }, "backgrounds": { "name": "Backgrounds", - "description": "List of HSV sequences (Max 16)." + "description": "[%key:component::tplink::services::sequence_effect::fields::sequence::description%]" }, "segments": { "name": "Segments", @@ -82,15 +82,15 @@ }, "brightness": { "name": "Brightness", - "description": "Initial brightness." + "description": "[%key:component::tplink::services::sequence_effect::fields::brightness::description%]" }, "duration": { "name": "Duration", - "description": "Duration." + "description": "[%key:component::tplink::services::sequence_effect::fields::duration::description%]" }, "transition": { "name": "Transition", - "description": "Transition." + "description": "[%key:component::tplink::services::sequence_effect::fields::transition::description%]" }, "fadeoff": { "name": "Fade off", diff --git a/homeassistant/components/transmission/strings.json b/homeassistant/components/transmission/strings.json index c3fdcc8f1f4d84..97741bd65bb0bc 100644 --- a/homeassistant/components/transmission/strings.json +++ b/homeassistant/components/transmission/strings.json @@ -45,7 +45,7 @@ "sensor": { "transmission_status": { "state": { - "idle": "Idle", + "idle": "[%key:common::state::idle%]", "up_down": "Up/Down", "seeding": "Seeding", "downloading": "Downloading" @@ -73,8 +73,8 @@ "description": "Removes a torrent.", "fields": { "entry_id": { - "name": "Transmission entry", - "description": "Config entry id." + "name": "[%key:component::transmission::services::add_torrent::fields::entry_id::name%]", + "description": "[%key:component::transmission::services::add_torrent::fields::entry_id::description%]" }, "id": { "name": "ID", @@ -91,12 +91,12 @@ "description": "Starts a torrent.", "fields": { "entry_id": { - "name": "Transmission entry", - "description": "Config entry id." + "name": "[%key:component::transmission::services::add_torrent::fields::entry_id::name%]", + "description": "[%key:component::transmission::services::add_torrent::fields::entry_id::description%]" }, "id": { "name": "ID", - "description": "ID of a torrent." + "description": "[%key:component::transmission::services::remove_torrent::fields::id::description%]" } } }, @@ -105,12 +105,12 @@ "description": "Stops a torrent.", "fields": { "entry_id": { - "name": "Transmission entry", - "description": "Config entry id." + "name": "[%key:component::transmission::services::add_torrent::fields::entry_id::name%]", + "description": "[%key:component::transmission::services::add_torrent::fields::entry_id::description%]" }, "id": { "name": "ID", - "description": "ID of a torrent." + "description": "[%key:component::transmission::services::remove_torrent::fields::id::description%]" } } } diff --git a/homeassistant/components/tuya/strings.json b/homeassistant/components/tuya/strings.json index f4443e89f76029..ccb7d878a4989f 100644 --- a/homeassistant/components/tuya/strings.json +++ b/homeassistant/components/tuya/strings.json @@ -21,7 +21,7 @@ "select": { "basic_anti_flicker": { "state": { - "0": "Disabled", + "0": "[%key:common::state::disabled%]", "1": "50 Hz", "2": "60 Hz" } @@ -61,9 +61,9 @@ }, "motion_sensitivity": { "state": { - "0": "Low sensitivity", + "0": "[%key:component::tuya::entity::select::decibel_sensitivity::state::0%]", "1": "Medium sensitivity", - "2": "High sensitivity" + "2": "[%key:component::tuya::entity::select::decibel_sensitivity::state::1%]" } }, "record_mode": { @@ -75,7 +75,7 @@ "relay_status": { "state": { "last": "Remember last state", - "memory": "Remember last state", + "memory": "[%key:component::tuya::entity::select::relay_status::state::last%]", "off": "[%key:common::state::off%]", "on": "[%key:common::state::on%]", "power_off": "[%key:common::state::off%]", @@ -105,7 +105,7 @@ }, "vacuum_mode": { "state": { - "standby": "Standby", + "standby": "[%key:common::state::standby%]", "random": "Random", "smart": "Smart", "wall_follow": "Follow Wall", @@ -199,7 +199,7 @@ "reserve_1": "Reserve 1", "reserve_2": "Reserve 2", "reserve_3": "Reserve 3", - "standby": "Standby", + "standby": "[%key:common::state::standby%]", "warm": "Heat preservation" } }, diff --git a/homeassistant/components/unifi/strings.json b/homeassistant/components/unifi/strings.json index 6afae5ffe7b83e..e441d4695ed2c9 100644 --- a/homeassistant/components/unifi/strings.json +++ b/homeassistant/components/unifi/strings.json @@ -75,7 +75,7 @@ "description": "Tries to get wireless client to reconnect to UniFi Network.", "fields": { "device_id": { - "name": "Device", + "name": "[%key:common::config_flow::data::device%]", "description": "Try reconnect client to wireless network." } } diff --git a/homeassistant/components/unifiprotect/strings.json b/homeassistant/components/unifiprotect/strings.json index fd2287e08be23f..73ac6e08c1756c 100644 --- a/homeassistant/components/unifiprotect/strings.json +++ b/homeassistant/components/unifiprotect/strings.json @@ -66,7 +66,7 @@ "description": "You are using v{version} of UniFi Protect which is an Early Access version. [Early Access versions are not supported by Home Assistant](https://www.home-assistant.io/integrations/unifiprotect#about-unifi-early-access) and it is recommended to go back to a stable release as soon as possible.\n\nBy submitting this form you have either [downgraded UniFi Protect](https://www.home-assistant.io/integrations/unifiprotect#downgrading-unifi-protect) or you agree to run an unsupported version of UniFi Protect." }, "confirm": { - "title": "v{version} is an Early Access version", + "title": "[%key:component::unifiprotect::issues::ea_warning::fix_flow::step::start::title%]", "description": "Are you sure you want to run unsupported versions of UniFi Protect? This may cause your Home Assistant integration to break." } } @@ -106,11 +106,11 @@ "description": "Removes an existing message for doorbells.", "fields": { "device_id": { - "name": "UniFi Protect NVR", - "description": "Any device from the UniFi Protect instance you want to change. In case you have multiple Protect Instances." + "name": "[%key:component::unifiprotect::services::add_doorbell_text::fields::device_id::name%]", + "description": "[%key:component::unifiprotect::services::add_doorbell_text::fields::device_id::description%]" }, "message": { - "name": "Custom message", + "name": "[%key:component::unifiprotect::services::add_doorbell_text::fields::message::name%]", "description": "Existing custom message to remove for doorbells." } } @@ -120,8 +120,8 @@ "description": "Sets the default doorbell message. This will be the message that is automatically selected when a message \"expires\".", "fields": { "device_id": { - "name": "UniFi Protect NVR", - "description": "Any device from the UniFi Protect instance you want to change. In case you have multiple Protect Instances." + "name": "[%key:component::unifiprotect::services::add_doorbell_text::fields::device_id::name%]", + "description": "[%key:component::unifiprotect::services::add_doorbell_text::fields::device_id::description%]" }, "message": { "name": "Default message", diff --git a/homeassistant/components/upb/strings.json b/homeassistant/components/upb/strings.json index b5b6dea93d5f7c..7e4590d35a2f80 100644 --- a/homeassistant/components/upb/strings.json +++ b/homeassistant/components/upb/strings.json @@ -48,7 +48,7 @@ "description": "Blinks a light.", "fields": { "rate": { - "name": "Rate", + "name": "[%key:component::upb::services::light_fade_start::fields::rate::name%]", "description": "Amount of time that the link flashes on." } } @@ -66,11 +66,11 @@ "description": "Number indicating brightness, where 0 turns the scene off, 1 is the minimum brightness and 255 is the maximum brightness." }, "brightness_pct": { - "name": "Brightness percentage", + "name": "[%key:component::upb::services::light_fade_start::fields::brightness_pct::name%]", "description": "Number indicating percentage of full brightness, where 0 turns the scene off, 1 is the minimum brightness and 100 is the maximum brightness." }, "rate": { - "name": "Rate", + "name": "[%key:component::upb::services::light_fade_start::fields::rate::name%]", "description": "Amount of time for scene to transition to new brightness." } } @@ -81,15 +81,15 @@ "fields": { "brightness": { "name": "Brightness", - "description": "Number indicating brightness, where 0 turns the scene off, 1 is the minimum brightness and 255 is the maximum brightness." + "description": "[%key:component::upb::services::link_goto::fields::brightness::description%]" }, "brightness_pct": { - "name": "Brightness percentage", - "description": "Number indicating percentage of full brightness, where 0 turns the scene off, 1 is the minimum brightness and 100 is the maximum brightness." + "name": "[%key:component::upb::services::light_fade_start::fields::brightness_pct::name%]", + "description": "[%key:component::upb::services::link_goto::fields::brightness_pct::description%]" }, "rate": { - "name": "Rate", - "description": "Amount of time for scene to transition to new brightness." + "name": "[%key:component::upb::services::light_fade_start::fields::rate::name%]", + "description": "[%key:component::upb::services::link_goto::fields::rate::description%]" } } }, @@ -103,7 +103,7 @@ "fields": { "blink_rate": { "name": "Blink rate", - "description": "Amount of time that the link flashes on." + "description": "[%key:component::upb::services::light_blink::fields::rate::description%]" } } } diff --git a/homeassistant/components/upnp/strings.json b/homeassistant/components/upnp/strings.json index 45d0c7de1c832f..ea052f0b45a3b9 100644 --- a/homeassistant/components/upnp/strings.json +++ b/homeassistant/components/upnp/strings.json @@ -7,7 +7,7 @@ }, "user": { "data": { - "unique_id": "Device" + "unique_id": "[%key:common::config_flow::data::device%]" } } }, diff --git a/homeassistant/components/uptimerobot/strings.json b/homeassistant/components/uptimerobot/strings.json index 8fccc3cb9e9860..588dc3ebf5cbf4 100644 --- a/homeassistant/components/uptimerobot/strings.json +++ b/homeassistant/components/uptimerobot/strings.json @@ -35,7 +35,7 @@ "state": { "down": "Down", "not_checked_yet": "Not checked yet", - "pause": "Pause", + "pause": "[%key:common::action::pause%]", "seems_down": "Seems down", "up": "Up" } diff --git a/homeassistant/components/utility_meter/strings.json b/homeassistant/components/utility_meter/strings.json index 09b9dd0954046a..f38989b536eba3 100644 --- a/homeassistant/components/utility_meter/strings.json +++ b/homeassistant/components/utility_meter/strings.json @@ -8,7 +8,7 @@ "data": { "cycle": "Meter reset cycle", "delta_values": "Delta values", - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "periodically_resetting": "Periodically resetting", "net_consumption": "Net consumption", "offset": "Meter reset offset", diff --git a/homeassistant/components/vallox/strings.json b/homeassistant/components/vallox/strings.json index b33cef0026aaf1..42efaeb053871b 100644 --- a/homeassistant/components/vallox/strings.json +++ b/homeassistant/components/vallox/strings.json @@ -36,7 +36,7 @@ "fields": { "fan_speed": { "name": "Fan speed", - "description": "Fan speed." + "description": "[%key:component::vallox::services::set_profile_fan_speed_home::fields::fan_speed::description%]" } } }, @@ -46,7 +46,7 @@ "fields": { "fan_speed": { "name": "Fan speed", - "description": "Fan speed." + "description": "[%key:component::vallox::services::set_profile_fan_speed_home::fields::fan_speed::description%]" } } } diff --git a/homeassistant/components/velbus/strings.json b/homeassistant/components/velbus/strings.json index bef853001a1744..948c079444de6f 100644 --- a/homeassistant/components/velbus/strings.json +++ b/homeassistant/components/velbus/strings.json @@ -33,8 +33,8 @@ "description": "Scans the velbus modules, this will be need if you see unknown module warnings in the logs, or when you added new modules.", "fields": { "interface": { - "name": "Interface", - "description": "The velbus interface to send the command to, this will be the same value as used during configuration." + "name": "[%key:component::velbus::services::sync_clock::fields::interface::name%]", + "description": "[%key:component::velbus::services::sync_clock::fields::interface::description%]" } } }, @@ -43,8 +43,8 @@ "description": "Clears the velbuscache and then starts a new scan.", "fields": { "interface": { - "name": "Interface", - "description": "The velbus interface to send the command to, this will be the same value as used during configuration." + "name": "[%key:component::velbus::services::sync_clock::fields::interface::name%]", + "description": "[%key:component::velbus::services::sync_clock::fields::interface::description%]" }, "address": { "name": "Address", @@ -57,8 +57,8 @@ "description": "Sets the memo text to the display of modules like VMBGPO, VMBGPOD Be sure the page(s) of the module is configured to display the memo text.\n.", "fields": { "interface": { - "name": "Interface", - "description": "The velbus interface to send the command to, this will be the same value as used during configuration." + "name": "[%key:component::velbus::services::sync_clock::fields::interface::name%]", + "description": "[%key:component::velbus::services::sync_clock::fields::interface::description%]" }, "address": { "name": "Address", diff --git a/homeassistant/components/vera/strings.json b/homeassistant/components/vera/strings.json index 4e51177910cabf..3bfb58f810412a 100644 --- a/homeassistant/components/vera/strings.json +++ b/homeassistant/components/vera/strings.json @@ -23,8 +23,8 @@ "title": "Vera controller options", "description": "See the vera documentation for details on optional parameters: https://www.home-assistant.io/integrations/vera/. Note: Any changes here will need a restart to the home assistant server. To clear values, provide a space.", "data": { - "lights": "Vera switch device ids to treat as lights in Home Assistant.", - "exclude": "Vera device ids to exclude from Home Assistant." + "lights": "[%key:component::vera::config::step::user::data::lights%]", + "exclude": "[%key:component::vera::config::step::user::data::exclude%]" } } } diff --git a/homeassistant/components/verisure/strings.json b/homeassistant/components/verisure/strings.json index 335daa68ee8a70..f715529b36bb7d 100644 --- a/homeassistant/components/verisure/strings.json +++ b/homeassistant/components/verisure/strings.json @@ -29,8 +29,8 @@ }, "reauth_mfa": { "data": { - "description": "Your account has 2-step verification enabled. Please enter the verification code Verisure sends to you.", - "code": "Verification Code" + "description": "[%key:component::verisure::config::step::mfa::data::description%]", + "code": "[%key:component::verisure::config::step::mfa::data::code%]" } } }, diff --git a/homeassistant/components/vizio/strings.json b/homeassistant/components/vizio/strings.json index 314f6f8b4e5f8f..0ff64eeda53e23 100644 --- a/homeassistant/components/vizio/strings.json +++ b/homeassistant/components/vizio/strings.json @@ -23,7 +23,7 @@ "description": "Your VIZIO SmartCast Device is now connected to Home Assistant." }, "pairing_complete_import": { - "title": "Pairing Complete", + "title": "[%key:component::vizio::config::step::pairing_complete::title%]", "description": "Your VIZIO SmartCast Device is now connected to Home Assistant.\n\nYour access token is '**{access_token}**'." } }, diff --git a/homeassistant/components/vulcan/strings.json b/homeassistant/components/vulcan/strings.json index bb9e1d4d8488dc..b2b270e3422fc7 100644 --- a/homeassistant/components/vulcan/strings.json +++ b/homeassistant/components/vulcan/strings.json @@ -25,11 +25,11 @@ } }, "reauth_confirm": { - "description": "Login to your Vulcan Account using mobile app registration page.", + "description": "[%key:component::vulcan::config::step::auth::description%]", "data": { "token": "Token", - "region": "Symbol", - "pin": "Pin" + "region": "[%key:component::vulcan::config::step::auth::data::region%]", + "pin": "[%key:component::vulcan::config::step::auth::data::pin%]" } }, "select_student": { diff --git a/homeassistant/components/webostv/strings.json b/homeassistant/components/webostv/strings.json index 985edb05645a5a..a5e7b73e59e294 100644 --- a/homeassistant/components/webostv/strings.json +++ b/homeassistant/components/webostv/strings.json @@ -15,8 +15,8 @@ "description": "Click submit and accept the pairing request on your TV.\n\n![Image](/static/images/config_webos.png)" }, "reauth_confirm": { - "title": "webOS TV Pairing", - "description": "Click submit and accept the pairing request on your TV.\n\n![Image](/static/images/config_webos.png)" + "title": "[%key:component::webostv::config::step::pairing::title%]", + "description": "[%key:component::webostv::config::step::pairing::description%]" } }, "error": { @@ -70,7 +70,7 @@ "fields": { "entity_id": { "name": "Entity", - "description": "Name(s) of the webostv entities where to run the API method." + "description": "[%key:component::webostv::services::button::fields::entity_id::description%]" }, "command": { "name": "Command", diff --git a/homeassistant/components/whirlpool/strings.json b/homeassistant/components/whirlpool/strings.json index aff89019e4ca63..94dc9aa219fe2a 100644 --- a/homeassistant/components/whirlpool/strings.json +++ b/homeassistant/components/whirlpool/strings.json @@ -27,7 +27,7 @@ "delay_countdown": "Delay Countdown", "delay_paused": "Delay Paused", "smart_delay": "Smart Delay", - "smart_grid_pause": "Smart Delay", + "smart_grid_pause": "[%key:component::whirlpool::entity::sensor::whirlpool_machine::state::smart_delay%]", "pause": "[%key:common::state::paused%]", "running_maincycle": "Running Maincycle", "running_postcycle": "Running Postcycle", diff --git a/homeassistant/components/wiz/strings.json b/homeassistant/components/wiz/strings.json index 2efa3c9a1c3438..656219f13bbe1c 100644 --- a/homeassistant/components/wiz/strings.json +++ b/homeassistant/components/wiz/strings.json @@ -13,7 +13,7 @@ }, "pick_device": { "data": { - "device": "Device" + "device": "[%key:common::config_flow::data::device%]" } } }, diff --git a/homeassistant/components/wolflink/strings.json b/homeassistant/components/wolflink/strings.json index 3de74cbbf4c782..b1c332984a1c12 100644 --- a/homeassistant/components/wolflink/strings.json +++ b/homeassistant/components/wolflink/strings.json @@ -18,7 +18,7 @@ }, "device": { "data": { - "device_name": "Device" + "device_name": "[%key:common::config_flow::data::device%]" }, "title": "Select WOLF device" } @@ -59,7 +59,7 @@ "spreizung_hoch": "dT too wide", "spreizung_kf": "Spread KF", "test": "Test", - "start": "Start", + "start": "[%key:common::action::start%]", "frost_heizkreis": "Heating circuit frost", "frost_warmwasser": "DHW frost", "schornsteinfeger": "Emissions test", diff --git a/homeassistant/components/workday/strings.json b/homeassistant/components/workday/strings.json index 4aaf241536fa7c..a217a7a36b1ab4 100644 --- a/homeassistant/components/workday/strings.json +++ b/homeassistant/components/workday/strings.json @@ -60,8 +60,8 @@ } }, "error": { - "add_holiday_error": "Incorrect format on date (YYYY-MM-DD)", - "remove_holiday_error": "Incorrect format on date (YYYY-MM-DD) or holiday name not found", + "add_holiday_error": "[%key:component::workday::config::error::add_holiday_error%]", + "remove_holiday_error": "[%key:component::workday::config::error::remove_holiday_error%]", "already_configured": "Service with this configuration already exist" } }, diff --git a/homeassistant/components/xiaomi_aqara/strings.json b/homeassistant/components/xiaomi_aqara/strings.json index 0944c91fd830f4..a77b78c5a0961f 100644 --- a/homeassistant/components/xiaomi_aqara/strings.json +++ b/homeassistant/components/xiaomi_aqara/strings.json @@ -54,8 +54,8 @@ "description": "Plays a specific ringtone. The version of the gateway firmware must be 1.4.1_145 at least.", "fields": { "gw_mac": { - "name": "Gateway MAC", - "description": "MAC address of the Xiaomi Aqara Gateway." + "name": "[%key:component::xiaomi_aqara::services::add_device::fields::gw_mac::name%]", + "description": "[%key:component::xiaomi_aqara::services::add_device::fields::gw_mac::description%]" }, "ringtone_id": { "name": "Ringtone ID", @@ -76,8 +76,8 @@ "description": "Hardware address of the device to remove." }, "gw_mac": { - "name": "Gateway MAC", - "description": "MAC address of the Xiaomi Aqara Gateway." + "name": "[%key:component::xiaomi_aqara::services::add_device::fields::gw_mac::name%]", + "description": "[%key:component::xiaomi_aqara::services::add_device::fields::gw_mac::description%]" } } }, @@ -86,8 +86,8 @@ "description": "Stops a playing ringtone immediately.", "fields": { "gw_mac": { - "name": "Gateway MAC", - "description": "MAC address of the Xiaomi Aqara Gateway." + "name": "[%key:component::xiaomi_aqara::services::add_device::fields::gw_mac::name%]", + "description": "[%key:component::xiaomi_aqara::services::add_device::fields::gw_mac::description%]" } } } diff --git a/homeassistant/components/xiaomi_miio/strings.json b/homeassistant/components/xiaomi_miio/strings.json index 578d2a96ff83f4..a9588855818d5e 100644 --- a/homeassistant/components/xiaomi_miio/strings.json +++ b/homeassistant/components/xiaomi_miio/strings.json @@ -53,7 +53,7 @@ }, "options": { "error": { - "cloud_credentials_incomplete": "Cloud credentials incomplete, please fill in username, password and country" + "cloud_credentials_incomplete": "[%key:component::xiaomi_miio::config::error::cloud_credentials_incomplete%]" }, "step": { "init": { @@ -112,7 +112,7 @@ "fields": { "entity_id": { "name": "Entity ID", - "description": "Name of the xiaomi miio entity." + "description": "[%key:component::xiaomi_miio::services::fan_reset_filter::fields::entity_id::description%]" }, "features": { "name": "Features", @@ -140,7 +140,7 @@ "fields": { "entity_id": { "name": "Entity ID", - "description": "Name of the light entity." + "description": "[%key:component::xiaomi_miio::services::light_set_scene::fields::entity_id::description%]" }, "time_period": { "name": "Time period", @@ -164,7 +164,7 @@ "fields": { "entity_id": { "name": "Entity ID", - "description": "Name of the entity to act on." + "description": "[%key:component::xiaomi_miio::services::light_reminder_on::fields::entity_id::description%]" } } }, @@ -174,7 +174,7 @@ "fields": { "entity_id": { "name": "Entity ID", - "description": "Name of the entity to act on." + "description": "[%key:component::xiaomi_miio::services::light_reminder_on::fields::entity_id::description%]" } } }, @@ -184,27 +184,27 @@ "fields": { "entity_id": { "name": "Entity ID", - "description": "Name of the entity to act on." + "description": "[%key:component::xiaomi_miio::services::light_reminder_on::fields::entity_id::description%]" } } }, "light_eyecare_mode_on": { "name": "Light eyecare mode on", - "description": "Enables the eye fatigue reminder/notification (EYECARE SMART LAMP 2 ONLY).", + "description": "[%key:component::xiaomi_miio::services::light_reminder_on::description%]", "fields": { "entity_id": { "name": "Entity ID", - "description": "Name of the entity to act on." + "description": "[%key:component::xiaomi_miio::services::light_reminder_on::fields::entity_id::description%]" } } }, "light_eyecare_mode_off": { "name": "Light eyecare mode off", - "description": "Disables the eye fatigue reminder/notification (EYECARE SMART LAMP 2 ONLY).", + "description": "[%key:component::xiaomi_miio::services::light_reminder_off::description%]", "fields": { "entity_id": { "name": "Entity ID", - "description": "Name of the entity to act on." + "description": "[%key:component::xiaomi_miio::services::light_reminder_on::fields::entity_id::description%]" } } }, @@ -236,7 +236,7 @@ "fields": { "entity_id": { "name": "Entity ID", - "description": "Name of the xiaomi miio entity." + "description": "[%key:component::xiaomi_miio::services::fan_reset_filter::fields::entity_id::description%]" } } }, @@ -246,7 +246,7 @@ "fields": { "entity_id": { "name": "Entity ID", - "description": "Name of the xiaomi miio entity." + "description": "[%key:component::xiaomi_miio::services::fan_reset_filter::fields::entity_id::description%]" } } }, @@ -256,10 +256,10 @@ "fields": { "entity_id": { "name": "Entity ID", - "description": "Name of the xiaomi miio entity." + "description": "[%key:component::xiaomi_miio::services::fan_reset_filter::fields::entity_id::description%]" }, "mode": { - "name": "Mode", + "name": "[%key:common::config_flow::data::mode%]", "description": "Power price." } } @@ -270,10 +270,10 @@ "fields": { "entity_id": { "name": "Entity ID", - "description": "Name of the xiaomi miio entity." + "description": "[%key:component::xiaomi_miio::services::fan_reset_filter::fields::entity_id::description%]" }, "mode": { - "name": "Mode", + "name": "[%key:common::config_flow::data::mode%]", "description": "Power mode." } } @@ -309,16 +309,16 @@ "description": "Remote controls the vacuum cleaner, only makes one move and then stops.", "fields": { "velocity": { - "name": "Velocity", - "description": "Speed." + "name": "[%key:component::xiaomi_miio::services::vacuum_remote_control_move::fields::velocity::name%]", + "description": "[%key:component::xiaomi_miio::services::vacuum_remote_control_move::fields::velocity::description%]" }, "rotation": { - "name": "Rotation", + "name": "[%key:component::xiaomi_miio::services::vacuum_remote_control_move::fields::rotation::name%]", "description": "Rotation." }, "duration": { "name": "Duration", - "description": "Duration of the movement." + "description": "[%key:component::xiaomi_miio::services::vacuum_remote_control_move::fields::duration::description%]" } } }, diff --git a/homeassistant/components/yale_smart_alarm/strings.json b/homeassistant/components/yale_smart_alarm/strings.json index 5928013e098235..ec0c5d0702a914 100644 --- a/homeassistant/components/yale_smart_alarm/strings.json +++ b/homeassistant/components/yale_smart_alarm/strings.json @@ -22,7 +22,7 @@ "username": "[%key:common::config_flow::data::username%]", "password": "[%key:common::config_flow::data::password%]", "name": "[%key:common::config_flow::data::name%]", - "area_id": "Area ID" + "area_id": "[%key:component::yale_smart_alarm::config::step::user::data::area_id%]" } } } diff --git a/homeassistant/components/yamaha/strings.json b/homeassistant/components/yamaha/strings.json index ddfee94aa0449e..ecb69d9fc38d2f 100644 --- a/homeassistant/components/yamaha/strings.json +++ b/homeassistant/components/yamaha/strings.json @@ -5,7 +5,7 @@ "description": "Enables or disables an output port.", "fields": { "port": { - "name": "Port", + "name": "[%key:common::config_flow::data::port%]", "description": "Name of port to enable/disable." }, "enabled": { diff --git a/homeassistant/components/yamaha_musiccast/strings.json b/homeassistant/components/yamaha_musiccast/strings.json index af26ed13b38779..c4f28fc750bf9f 100644 --- a/homeassistant/components/yamaha_musiccast/strings.json +++ b/homeassistant/components/yamaha_musiccast/strings.json @@ -45,7 +45,7 @@ }, "zone_surr_decoder_type": { "state": { - "toggle": "Toggle", + "toggle": "[%key:common::action::toggle%]", "auto": "Auto", "dolby_pl": "Dolby ProLogic", "dolby_pl2x_movie": "Dolby ProLogic 2x Movie", @@ -61,7 +61,7 @@ "state": { "manual": "Manual", "auto": "Auto", - "bypass": "Bypass" + "bypass": "[%key:component::yamaha_musiccast::entity::select::zone_tone_control_mode::state::bypass%]" } }, "zone_link_audio_quality": { diff --git a/homeassistant/components/yeelight/strings.json b/homeassistant/components/yeelight/strings.json index 18b762057a78bb..03a93bd9a5bfe4 100644 --- a/homeassistant/components/yeelight/strings.json +++ b/homeassistant/components/yeelight/strings.json @@ -10,7 +10,7 @@ }, "pick_device": { "data": { - "device": "Device" + "device": "[%key:common::config_flow::data::device%]" } }, "discovery_confirm": { @@ -29,7 +29,7 @@ "step": { "init": { "data": { - "model": "Model", + "model": "[%key:common::generic::model%]", "transition": "Transition Time (ms)", "use_music_mode": "Enable Music Mode", "save_on_change": "Save Status On Change", @@ -44,7 +44,7 @@ "description": "Sets a operation mode.", "fields": { "mode": { - "name": "Mode", + "name": "[%key:common::config_flow::data::mode%]", "description": "Operation mode." } } @@ -73,7 +73,7 @@ }, "brightness": { "name": "Brightness", - "description": "The brightness value to set." + "description": "[%key:component::yeelight::services::set_color_scene::fields::brightness::description%]" } } }, @@ -87,7 +87,7 @@ }, "brightness": { "name": "Brightness", - "description": "The brightness value to set." + "description": "[%key:component::yeelight::services::set_color_scene::fields::brightness::description%]" } } }, @@ -119,7 +119,7 @@ }, "brightness": { "name": "Brightness", - "description": "The brightness value to set." + "description": "[%key:component::yeelight::services::set_color_scene::fields::brightness::description%]" } } }, @@ -129,15 +129,15 @@ "fields": { "count": { "name": "Count", - "description": "The number of times to run this flow (0 to run forever)." + "description": "[%key:component::yeelight::services::set_color_flow_scene::fields::count::description%]" }, "action": { "name": "Action", - "description": "The action to take after the flow stops." + "description": "[%key:component::yeelight::services::set_color_flow_scene::fields::action::description%]" }, "transitions": { - "name": "Transitions", - "description": "Array of transitions, for desired effect. Examples https://yeelight.readthedocs.io/en/stable/flow.html." + "name": "[%key:component::yeelight::services::set_color_flow_scene::fields::transitions::name%]", + "description": "[%key:component::yeelight::services::set_color_flow_scene::fields::transitions::description%]" } } }, @@ -165,7 +165,7 @@ }, "action": { "options": { - "off": "Off", + "off": "[%key:common::state::off%]", "recover": "Recover", "stay": "Stay" } diff --git a/homeassistant/components/youtube/strings.json b/homeassistant/components/youtube/strings.json index 1ecc2bc4db84eb..7f369e9909bd91 100644 --- a/homeassistant/components/youtube/strings.json +++ b/homeassistant/components/youtube/strings.json @@ -27,9 +27,9 @@ "options": { "step": { "init": { - "description": "Select the channels you want to add.", + "description": "[%key:component::youtube::config::step::channels::description%]", "data": { - "channels": "YouTube channels" + "channels": "[%key:component::youtube::config::step::channels::data::channels%]" } } } diff --git a/homeassistant/components/zamg/strings.json b/homeassistant/components/zamg/strings.json index f0a607f2da7da8..a92e7aa605e2b0 100644 --- a/homeassistant/components/zamg/strings.json +++ b/homeassistant/components/zamg/strings.json @@ -16,7 +16,7 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", - "station_not_found": "Station ID not found at zamg" + "station_not_found": "[%key:component::zamg::config::error::station_not_found%]" } } } diff --git a/homeassistant/components/zha/strings.json b/homeassistant/components/zha/strings.json index 50eadfc6667f83..1e44191a762e0f 100644 --- a/homeassistant/components/zha/strings.json +++ b/homeassistant/components/zha/strings.json @@ -19,7 +19,7 @@ "data": { "radio_type": "Radio Type" }, - "title": "Radio Type", + "title": "[%key:component::zha::config::step::manual_pick_radio_type::data::radio_type%]", "description": "Pick your Zigbee radio type" }, "manual_port_config": { @@ -94,7 +94,7 @@ } }, "intent_migrate": { - "title": "Migrate to a new radio", + "title": "[%key:component::zha::options::step::prompt_migrate_or_reconfigure::menu_options::intent_migrate%]", "description": "Before plugging in your new radio, your old radio needs to be reset. An automatic backup will be performed. If you are using a combined Z-Wave and Zigbee adapter like the HUSBZB-1, this will only reset the Zigbee portion.\n\n*Note: if you are migrating from a **ConBee/RaspBee**, make sure it is running firmware `0x26720700` or newer! Otherwise, some devices may not be controllable after migrating until they are power cycled.*\n\nDo you wish to continue?" }, "instruct_unplug": { @@ -367,8 +367,8 @@ "description": "Parameters to pass to the command." }, "manufacturer": { - "name": "Manufacturer", - "description": "Manufacturer code." + "name": "[%key:component::zha::services::set_zigbee_cluster_attribute::fields::manufacturer::name%]", + "description": "[%key:component::zha::services::set_zigbee_cluster_attribute::fields::manufacturer::description%]" } } }, @@ -381,24 +381,24 @@ "description": "Hexadecimal address of the group." }, "cluster_id": { - "name": "Cluster ID", + "name": "[%key:component::zha::services::set_zigbee_cluster_attribute::fields::cluster_id::name%]", "description": "ZCL cluster to send command to." }, "cluster_type": { "name": "Cluster type", - "description": "Type of the cluster." + "description": "[%key:component::zha::services::set_zigbee_cluster_attribute::fields::cluster_type::description%]" }, "command": { "name": "Command", - "description": "ID of the command to execute." + "description": "[%key:component::zha::services::issue_zigbee_cluster_command::fields::command::description%]" }, "args": { "name": "Args", - "description": "Arguments to pass to the command." + "description": "[%key:component::zha::services::issue_zigbee_cluster_command::fields::args::description%]" }, "manufacturer": { - "name": "Manufacturer", - "description": "Manufacturer code." + "name": "[%key:component::zha::services::set_zigbee_cluster_attribute::fields::manufacturer::name%]", + "description": "[%key:component::zha::services::set_zigbee_cluster_attribute::fields::manufacturer::description%]" } } }, @@ -408,11 +408,11 @@ "fields": { "ieee": { "name": "[%key:component::zha::services::permit::fields::ieee::name%]", - "description": "IEEE address for the device." + "description": "[%key:component::zha::services::set_zigbee_cluster_attribute::fields::ieee::description%]" }, "mode": { - "name": "Mode", - "description": "The Squawk Mode field is used as a 4-bit enumeration, and can have one of the values shown in Table 8-24 of the ZCL spec - Squawk Mode Field. The exact operation of each mode (how the WD \u201csquawks\u201d) is implementation specific." + "name": "[%key:common::config_flow::data::mode%]", + "description": "The Squawk Mode field is used as a 4-bit enumeration, and can have one of the values shown in Table 8-24 of the ZCL spec - Squawk Mode Field. The exact operation of each mode (how the WD “squawks”) is implementation specific." }, "strobe": { "name": "Strobe", @@ -430,15 +430,15 @@ "fields": { "ieee": { "name": "[%key:component::zha::services::permit::fields::ieee::name%]", - "description": "IEEE address for the device." + "description": "[%key:component::zha::services::set_zigbee_cluster_attribute::fields::ieee::description%]" }, "mode": { - "name": "Mode", + "name": "[%key:common::config_flow::data::mode%]", "description": "The Warning Mode field is used as an 4-bit enumeration, can have one of the values 0-6 defined below in table 8-20 of the ZCL spec. The exact behavior of the WD device in each mode is according to the relevant security standards." }, "strobe": { - "name": "Strobe", - "description": "The Strobe field is used as a 2-bit enumeration, and determines if the visual indication is required in addition to the audible siren, as indicated in Table 8-21 of the ZCL spec. \"0\" means no strobe, \"1\" means strobe. If the strobe field is \u201c1\u201d and the Warning Mode is \u201c0\u201d (\u201cStop\u201d) then only the strobe is activated." + "name": "[%key:component::zha::services::warning_device_squawk::fields::strobe::name%]", + "description": "The Strobe field is used as a 2-bit enumeration, and determines if the visual indication is required in addition to the audible siren, as indicated in Table 8-21 of the ZCL spec. \"0\" means no strobe, \"1\" means strobe. If the strobe field is “1” and the Warning Mode is “0” (“Stop”) then only the strobe is activated." }, "level": { "name": "Level", @@ -450,7 +450,7 @@ }, "duty_cycle": { "name": "Duty cycle", - "description": "Indicates the length of the flash cycle. This allows you to vary the flash duration for different alarm types (e.g., fire, police, burglar). The valid range is 0-100 in increments of 10. All other values must be rounded to the nearest valid value. Strobe calculates a duty cycle over a duration of one second. The ON state must precede the OFF state. For example, if Strobe Duty Cycle Field specifies \u201c40,\u201d, then the strobe flashes ON for 4/10ths of a second and then turns OFF for 6/10ths of a second." + "description": "Indicates the length of the flash cycle. This allows you to vary the flash duration for different alarm types (e.g., fire, police, burglar). The valid range is 0-100 in increments of 10. All other values must be rounded to the nearest valid value. Strobe calculates a duty cycle over a duration of one second. The ON state must precede the OFF state. For example, if Strobe Duty Cycle Field specifies “40,”, then the strobe flashes ON for 4/10ths of a second and then turns OFF for 6/10ths of a second." }, "intensity": { "name": "Intensity", diff --git a/homeassistant/components/zoneminder/strings.json b/homeassistant/components/zoneminder/strings.json index 1e2e41d274107e..34e8b8454720f6 100644 --- a/homeassistant/components/zoneminder/strings.json +++ b/homeassistant/components/zoneminder/strings.json @@ -5,7 +5,7 @@ "description": "Sets the ZoneMinder run state.", "fields": { "name": { - "name": "Name", + "name": "[%key:common::config_flow::data::name%]", "description": "The string name of the ZoneMinder run state to set as active." } } diff --git a/homeassistant/components/zwave_js/strings.json b/homeassistant/components/zwave_js/strings.json index 37b4577e5dfc10..3b86cbdd5a4bf3 100644 --- a/homeassistant/components/zwave_js/strings.json +++ b/homeassistant/components/zwave_js/strings.json @@ -74,50 +74,50 @@ } }, "on_supervisor": { - "title": "Select connection method", - "description": "Do you want to use the Z-Wave JS Supervisor add-on?", + "title": "[%key:component::zwave_js::config::step::on_supervisor::title%]", + "description": "[%key:component::zwave_js::config::step::on_supervisor::description%]", "data": { - "use_addon": "Use the Z-Wave JS Supervisor add-on" + "use_addon": "[%key:component::zwave_js::config::step::on_supervisor::data::use_addon%]" } }, "install_addon": { - "title": "The Z-Wave JS add-on installation has started" + "title": "[%key:component::zwave_js::config::step::install_addon::title%]" }, "configure_addon": { - "title": "Enter the Z-Wave JS add-on configuration", - "description": "The add-on will generate security keys if those fields are left empty.", + "title": "[%key:component::zwave_js::config::step::configure_addon::title%]", + "description": "[%key:component::zwave_js::config::step::configure_addon::description%]", "data": { "usb_path": "[%key:common::config_flow::data::usb_path%]", - "s0_legacy_key": "S0 Key (Legacy)", - "s2_authenticated_key": "S2 Authenticated Key", - "s2_unauthenticated_key": "S2 Unauthenticated Key", - "s2_access_control_key": "S2 Access Control Key", + "s0_legacy_key": "[%key:component::zwave_js::config::step::configure_addon::data::s0_legacy_key%]", + "s2_authenticated_key": "[%key:component::zwave_js::config::step::configure_addon::data::s2_authenticated_key%]", + "s2_unauthenticated_key": "[%key:component::zwave_js::config::step::configure_addon::data::s2_unauthenticated_key%]", + "s2_access_control_key": "[%key:component::zwave_js::config::step::configure_addon::data::s2_access_control_key%]", "log_level": "Log level", "emulate_hardware": "Emulate Hardware" } }, "start_addon": { - "title": "The Z-Wave JS add-on is starting." + "title": "[%key:component::zwave_js::config::step::start_addon::title%]" } }, "error": { - "invalid_ws_url": "Invalid websocket URL", + "invalid_ws_url": "[%key:component::zwave_js::config::error::invalid_ws_url%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "unknown": "[%key:common::config_flow::error::unknown%]" }, "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", - "addon_info_failed": "Failed to get Z-Wave JS add-on info.", - "addon_install_failed": "Failed to install the Z-Wave JS add-on.", - "addon_set_config_failed": "Failed to set Z-Wave JS configuration.", - "addon_start_failed": "Failed to start the Z-Wave JS add-on.", - "addon_get_discovery_info_failed": "Failed to get Z-Wave JS add-on discovery info.", + "addon_info_failed": "[%key:component::zwave_js::config::abort::addon_info_failed%]", + "addon_install_failed": "[%key:component::zwave_js::config::abort::addon_install_failed%]", + "addon_set_config_failed": "[%key:component::zwave_js::config::abort::addon_set_config_failed%]", + "addon_start_failed": "[%key:component::zwave_js::config::abort::addon_start_failed%]", + "addon_get_discovery_info_failed": "[%key:component::zwave_js::config::abort::addon_get_discovery_info_failed%]", "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "different_device": "The connected USB device is not the same as previously configured for this config entry. Please instead create a new config entry for the new device." }, "progress": { - "install_addon": "Please wait while the Z-Wave JS add-on installation finishes. This can take several minutes.", - "start_addon": "Please wait while the Z-Wave JS add-on start completes. This may take some seconds." + "install_addon": "[%key:component::zwave_js::config::progress::install_addon%]", + "start_addon": "[%key:component::zwave_js::config::progress::start_addon%]" } }, "device_automation": { diff --git a/homeassistant/components/zwave_me/strings.json b/homeassistant/components/zwave_me/strings.json index 63add194d08e66..0c5a1d30976f7d 100644 --- a/homeassistant/components/zwave_me/strings.json +++ b/homeassistant/components/zwave_me/strings.json @@ -14,7 +14,7 @@ }, "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", - "no_valid_uuid_set": "No valid UUID set" + "no_valid_uuid_set": "[%key:component::zwave_me::config::error::no_valid_uuid_set%]" } } } diff --git a/script/translations/deduplicate.py b/script/translations/deduplicate.py new file mode 100644 index 00000000000000..86812318218b80 --- /dev/null +++ b/script/translations/deduplicate.py @@ -0,0 +1,131 @@ +"""Deduplicate translations in strings.json.""" + + +import argparse +import json +from pathlib import Path + +from homeassistant.const import Platform + +from . import upload +from .develop import flatten_translations +from .util import get_base_arg_parser + + +def get_arguments() -> argparse.Namespace: + """Get parsed passed in arguments.""" + parser = get_base_arg_parser() + parser.add_argument( + "--limit-reference", + "--lr", + action="store_true", + help="Only allow references to same strings.json or common.", + ) + return parser.parse_args() + + +STRINGS_PATH = "homeassistant/components/{}/strings.json" +ENTITY_COMPONENT_PREFIX = tuple(f"component::{domain}::" for domain in Platform) + + +def run(): + """Clean translations.""" + args = get_arguments() + translations = upload.generate_upload_data() + flattened_translations = flatten_translations(translations) + flattened_translations = { + key: value + for key, value in flattened_translations.items() + # Skip existing references + if not value.startswith("[%key:") + } + + primary = {} + secondary = {} + + for key, value in flattened_translations.items(): + if key.startswith("common::"): + primary[value] = key + elif key.startswith(ENTITY_COMPONENT_PREFIX): + primary.setdefault(value, key) + else: + secondary.setdefault(value, key) + + merged = {**secondary, **primary} + + # Questionable translations are ones that are duplicate but are not referenced + # by the common strings.json or strings.json from an entity component. + questionable = set(secondary.values()) + suggest_new_common = set() + update_keys = {} + + for key, value in flattened_translations.items(): + if merged[value] == key or key.startswith("common::"): + continue + + key_integration = key.split("::")[1] + + key_to_reference = merged[value] + key_to_reference_integration = key_to_reference.split("::")[1] + is_common = key_to_reference.startswith("common::") + + # If we want to only add references to own integrations + # but not include entity integrations + if ( + args.limit_reference + and (key_integration != key_to_reference_integration and not is_common) + # Do not create self-references in entity integrations + or key_integration in Platform.__members__.values() + ): + continue + + if ( + # We don't want integrations to reference arbitrary other integrations + key_to_reference in questionable + # Allow reference own integration + and key_to_reference_integration != key_integration + ): + suggest_new_common.add(value) + continue + + update_keys[key] = f"[%key:{key_to_reference}%]" + + if suggest_new_common: + print("Suggested new common words:") + for key in sorted(suggest_new_common): + print(key) + + components = sorted({key.split("::")[1] for key in update_keys}) + + strings = {} + + for component in components: + comp_strings_path = Path(STRINGS_PATH.format(component)) + strings[component] = json.loads(comp_strings_path.read_text(encoding="utf-8")) + + for path, value in update_keys.items(): + parts = path.split("::") + parts.pop(0) + component = parts.pop(0) + to_write = strings[component] + while len(parts) > 1: + try: + to_write = to_write[parts.pop(0)] + except KeyError: + print(to_write) + raise + + to_write[parts.pop(0)] = value + + for component in components: + comp_strings_path = Path(STRINGS_PATH.format(component)) + comp_strings_path.write_text( + json.dumps( + strings[component], + indent=2, + ensure_ascii=False, + ), + encoding="utf-8", + ) + + return 0 diff --git a/script/translations/develop.py b/script/translations/develop.py index a318c7c08bc97e..3bfaa279e93591 100644 --- a/script/translations/develop.py +++ b/script/translations/develop.py @@ -92,6 +92,7 @@ def substitute_reference(value, flattened_translations): def run_single(translations, flattened_translations, integration): """Run the script for a single integration.""" + print(f"Generating translations for {integration}") if integration not in translations["component"]: print("Integration has no strings.json") @@ -114,8 +115,6 @@ def run_single(translations, flattened_translations, integration): download.write_integration_translations() - print(f"Generating translations for {integration}") - def run(): """Run the script.""" diff --git a/script/translations/util.py b/script/translations/util.py index 9839fefd9d540e..0c8c8a2a30f784 100644 --- a/script/translations/util.py +++ b/script/translations/util.py @@ -13,7 +13,15 @@ def get_base_arg_parser() -> argparse.ArgumentParser: parser.add_argument( "action", type=str, - choices=["clean", "develop", "download", "frontend", "migrate", "upload"], + choices=[ + "clean", + "deduplicate", + "develop", + "download", + "frontend", + "migrate", + "upload", + ], ) parser.add_argument("--debug", action="store_true", help="Enable log output") return parser From 025ed3868df866593ea2b25d447a0121bb98f1ad Mon Sep 17 00:00:00 2001 From: Mads Nedergaard Date: Thu, 13 Jul 2023 17:57:31 +0200 Subject: [PATCH 130/154] Rename CO2Signal to Electricity Maps (#96252) * Changes names and links * Changes link to documentation * Updates generated integration name --- homeassistant/components/co2signal/const.py | 2 +- homeassistant/components/co2signal/manifest.json | 4 ++-- homeassistant/components/co2signal/sensor.py | 6 +++--- homeassistant/components/co2signal/strings.json | 2 +- homeassistant/generated/integrations.json | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/co2signal/const.py b/homeassistant/components/co2signal/const.py index a1264acc9ff97f..1e0cbfe0f11275 100644 --- a/homeassistant/components/co2signal/const.py +++ b/homeassistant/components/co2signal/const.py @@ -3,4 +3,4 @@ DOMAIN = "co2signal" CONF_COUNTRY_CODE = "country_code" -ATTRIBUTION = "Data provided by CO2signal" +ATTRIBUTION = "Data provided by Electricity Maps" diff --git a/homeassistant/components/co2signal/manifest.json b/homeassistant/components/co2signal/manifest.json index b4dc01d03aa6d0..0c5e6f4139b21e 100644 --- a/homeassistant/components/co2signal/manifest.json +++ b/homeassistant/components/co2signal/manifest.json @@ -1,9 +1,9 @@ { "domain": "co2signal", - "name": "CO2 Signal", + "name": "Electricity Maps", "codeowners": [], "config_flow": true, - "documentation": "https://www.home-assistant.io/integrations/co2signal", + "documentation": "https://www.home-assistant.io/integrations/electricity_maps", "iot_class": "cloud_polling", "loggers": ["CO2Signal"], "requirements": ["CO2Signal==0.4.2"] diff --git a/homeassistant/components/co2signal/sensor.py b/homeassistant/components/co2signal/sensor.py index 9f133c0b0ca565..ae22fb7b7efa17 100644 --- a/homeassistant/components/co2signal/sensor.py +++ b/homeassistant/components/co2signal/sensor.py @@ -75,11 +75,11 @@ def __init__( "country_code": coordinator.data["countryCode"], } self._attr_device_info = DeviceInfo( - configuration_url="https://www.electricitymap.org/", + configuration_url="https://www.electricitymaps.com/", entry_type=DeviceEntryType.SERVICE, identifiers={(DOMAIN, coordinator.entry_id)}, - manufacturer="Tmrow.com", - name="CO2 signal", + manufacturer="Electricity Maps", + name="Electricity Maps", ) self._attr_unique_id = ( f"{coordinator.entry_id}_{description.unique_id or description.key}" diff --git a/homeassistant/components/co2signal/strings.json b/homeassistant/components/co2signal/strings.json index 78274b0586cfdf..01c5673d4b1b11 100644 --- a/homeassistant/components/co2signal/strings.json +++ b/homeassistant/components/co2signal/strings.json @@ -6,7 +6,7 @@ "location": "Get data for", "api_key": "[%key:common::config_flow::data::access_token%]" }, - "description": "Visit https://co2signal.com/ to request a token." + "description": "Visit https://electricitymaps.com/free-tier to request a token." }, "coordinates": { "data": { diff --git a/homeassistant/generated/integrations.json b/homeassistant/generated/integrations.json index 21f7acd59e39c0..4dcde6d883f6f8 100644 --- a/homeassistant/generated/integrations.json +++ b/homeassistant/generated/integrations.json @@ -846,7 +846,7 @@ "iot_class": "local_polling" }, "co2signal": { - "name": "CO2 Signal", + "name": "Electricity Maps", "integration_type": "hub", "config_flow": true, "iot_class": "cloud_polling" From fbbdebee47620b00ff3c200d2d7dea9d0c340ebd Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Thu, 13 Jul 2023 18:14:31 +0200 Subject: [PATCH 131/154] Correct unifi device info (#96483) --- homeassistant/components/unifi/controller.py | 1 - tests/components/unifi/test_controller.py | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/homeassistant/components/unifi/controller.py b/homeassistant/components/unifi/controller.py index 60507d5a8c6ba1..6ac4e6227369ca 100644 --- a/homeassistant/components/unifi/controller.py +++ b/homeassistant/components/unifi/controller.py @@ -345,7 +345,6 @@ async def async_update_device_registry(self) -> None: device_registry.async_get_or_create( config_entry_id=self.config_entry.entry_id, - configuration_url=self.api.url, connections={(CONNECTION_NETWORK_MAC, self.mac)}, default_manufacturer=ATTR_MANUFACTURER, default_model="UniFi Network", diff --git a/tests/components/unifi/test_controller.py b/tests/components/unifi/test_controller.py index e3efaef915b168..d0f387a3c6c05f 100644 --- a/tests/components/unifi/test_controller.py +++ b/tests/components/unifi/test_controller.py @@ -261,8 +261,7 @@ async def test_controller_mac( config_entry_id=config_entry.entry_id, connections={(CONNECTION_NETWORK_MAC, controller.mac)}, ) - - assert device_entry.configuration_url == controller.api.url + assert device_entry async def test_controller_not_accessible(hass: HomeAssistant) -> None: From 5b93017740a8153f5c1a4d4202b224f47326be90 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Thu, 13 Jul 2023 18:15:28 +0200 Subject: [PATCH 132/154] Correct huawei_lte device info (#96481) --- homeassistant/components/huawei_lte/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/homeassistant/components/huawei_lte/__init__.py b/homeassistant/components/huawei_lte/__init__.py index 95197dcbb49f52..3c101dff9cc67d 100644 --- a/homeassistant/components/huawei_lte/__init__.py +++ b/homeassistant/components/huawei_lte/__init__.py @@ -413,9 +413,8 @@ def _connect() -> Connection: device_info = DeviceInfo( configuration_url=router.url, connections=router.device_connections, - default_manufacturer=DEFAULT_MANUFACTURER, identifiers=router.device_identifiers, - manufacturer=entry.data.get(CONF_MANUFACTURER), + manufacturer=entry.data.get(CONF_MANUFACTURER, DEFAULT_MANUFACTURER), name=router.device_name, ) hw_version = None From 8440f14a08047a802e7188d62ad4f4149f79eff4 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Thu, 13 Jul 2023 18:15:46 +0200 Subject: [PATCH 133/154] Correct dlna_dmr device info (#96480) --- .../components/dlna_dmr/media_player.py | 2 - .../components/dlna_dmr/test_media_player.py | 41 +++++++++++++++---- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/dlna_dmr/media_player.py b/homeassistant/components/dlna_dmr/media_player.py index eddb2633beacfd..50877756d521fc 100644 --- a/homeassistant/components/dlna_dmr/media_player.py +++ b/homeassistant/components/dlna_dmr/media_player.py @@ -37,7 +37,6 @@ CONF_CALLBACK_URL_OVERRIDE, CONF_LISTEN_PORT, CONF_POLL_AVAILABILITY, - DOMAIN, LOGGER as _LOGGER, MEDIA_METADATA_DIDL, MEDIA_TYPE_MAP, @@ -381,7 +380,6 @@ def _update_device_registry(self, set_mac: bool = False) -> None: device_entry = dev_reg.async_get_or_create( config_entry_id=self.registry_entry.config_entry_id, connections=connections, - identifiers={(DOMAIN, self.unique_id)}, default_manufacturer=self._device.manufacturer, default_model=self._device.model_name, default_name=self._device.name, diff --git a/tests/components/dlna_dmr/test_media_player.py b/tests/components/dlna_dmr/test_media_player.py index e07e0b6cfcba44..f8413e8f6200cc 100644 --- a/tests/components/dlna_dmr/test_media_player.py +++ b/tests/components/dlna_dmr/test_media_player.py @@ -50,6 +50,7 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.device_registry import ( CONNECTION_NETWORK_MAC, + CONNECTION_UPNP, async_get as async_get_dr, ) from homeassistant.helpers.entity_component import async_update_entity @@ -347,7 +348,10 @@ async def test_setup_entry_mac_address( # Check the device registry connections for MAC address dev_reg = async_get_dr(hass) - device = dev_reg.async_get_device(identifiers={(DLNA_DOMAIN, MOCK_DEVICE_UDN)}) + device = dev_reg.async_get_device( + connections={(CONNECTION_UPNP, MOCK_DEVICE_UDN)}, + identifiers=set(), + ) assert device is not None assert (CONNECTION_NETWORK_MAC, MOCK_MAC_ADDRESS) in device.connections @@ -364,7 +368,10 @@ async def test_setup_entry_no_mac_address( # Check the device registry connections does not include the MAC address dev_reg = async_get_dr(hass) - device = dev_reg.async_get_device(identifiers={(DLNA_DOMAIN, MOCK_DEVICE_UDN)}) + device = dev_reg.async_get_device( + connections={(CONNECTION_UPNP, MOCK_DEVICE_UDN)}, + identifiers=set(), + ) assert device is not None assert (CONNECTION_NETWORK_MAC, MOCK_MAC_ADDRESS) not in device.connections @@ -427,7 +434,10 @@ async def test_available_device( """Test a DlnaDmrEntity with a connected DmrDevice.""" # Check hass device information is filled in dev_reg = async_get_dr(hass) - device = dev_reg.async_get_device(identifiers={(DLNA_DOMAIN, MOCK_DEVICE_UDN)}) + device = dev_reg.async_get_device( + connections={(CONNECTION_UPNP, MOCK_DEVICE_UDN)}, + identifiers=set(), + ) assert device is not None # Device properties are set in dmr_device_mock before the entity gets constructed assert device.manufacturer == "device_manufacturer" @@ -1323,7 +1333,10 @@ async def test_unavailable_device( # Check hass device information has not been filled in yet dev_reg = async_get_dr(hass) - device = dev_reg.async_get_device(identifiers={(DLNA_DOMAIN, MOCK_DEVICE_UDN)}) + device = dev_reg.async_get_device( + connections={(CONNECTION_UPNP, MOCK_DEVICE_UDN)}, + identifiers=set(), + ) assert device is None # Unload config entry to clean up @@ -1360,7 +1373,10 @@ async def test_become_available( # Check hass device information has not been filled in yet dev_reg = async_get_dr(hass) - device = dev_reg.async_get_device(identifiers={(DLNA_DOMAIN, MOCK_DEVICE_UDN)}) + device = dev_reg.async_get_device( + connections={(CONNECTION_UPNP, MOCK_DEVICE_UDN)}, + identifiers=set(), + ) assert device is None # Mock device is now available. @@ -1399,7 +1415,10 @@ async def test_become_available( assert mock_state.state == MediaPlayerState.IDLE # Check hass device information is now filled in dev_reg = async_get_dr(hass) - device = dev_reg.async_get_device(identifiers={(DLNA_DOMAIN, MOCK_DEVICE_UDN)}) + device = dev_reg.async_get_device( + connections={(CONNECTION_UPNP, MOCK_DEVICE_UDN)}, + identifiers=set(), + ) assert device is not None assert device.manufacturer == "device_manufacturer" assert device.model == "device_model_name" @@ -2231,7 +2250,10 @@ async def test_config_update_mac_address( # Check the device registry connections does not include the MAC address dev_reg = async_get_dr(hass) - device = dev_reg.async_get_device(identifiers={(DLNA_DOMAIN, MOCK_DEVICE_UDN)}) + device = dev_reg.async_get_device( + connections={(CONNECTION_UPNP, MOCK_DEVICE_UDN)}, + identifiers=set(), + ) assert device is not None assert (CONNECTION_NETWORK_MAC, MOCK_MAC_ADDRESS) not in device.connections @@ -2248,6 +2270,9 @@ async def test_config_update_mac_address( await hass.async_block_till_done() # Device registry connections should now include the MAC address - device = dev_reg.async_get_device(identifiers={(DLNA_DOMAIN, MOCK_DEVICE_UDN)}) + device = dev_reg.async_get_device( + connections={(CONNECTION_UPNP, MOCK_DEVICE_UDN)}, + identifiers=set(), + ) assert device is not None assert (CONNECTION_NETWORK_MAC, MOCK_MAC_ADDRESS) in device.connections From 580fd92ef2743d0f7f388a88032f16a215910758 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Thu, 13 Jul 2023 18:17:13 +0200 Subject: [PATCH 134/154] Correct knx device info (#96482) --- homeassistant/components/knx/device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/knx/device.py b/homeassistant/components/knx/device.py index 452de577ce0830..18e6197360a480 100644 --- a/homeassistant/components/knx/device.py +++ b/homeassistant/components/knx/device.py @@ -25,7 +25,7 @@ def __init__(self, hass: HomeAssistant, entry: ConfigEntry, xknx: XKNX) -> None: _device_id = (DOMAIN, f"_{entry.entry_id}_interface") self.device = self.device_registry.async_get_or_create( config_entry_id=entry.entry_id, - default_name="KNX Interface", + name="KNX Interface", identifiers={_device_id}, ) self.device_info = DeviceInfo(identifiers={_device_id}) From 5f4643605785bb67e5a9c3eb07a8ad9afd343646 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 13 Jul 2023 06:43:50 -1000 Subject: [PATCH 135/154] Bump yalexs-ble to 2.2.0 (#96460) --- homeassistant/components/august/manifest.json | 2 +- homeassistant/components/yalexs_ble/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/august/manifest.json b/homeassistant/components/august/manifest.json index ca4e799f16b0dd..31d0ff09467612 100644 --- a/homeassistant/components/august/manifest.json +++ b/homeassistant/components/august/manifest.json @@ -28,5 +28,5 @@ "documentation": "https://www.home-assistant.io/integrations/august", "iot_class": "cloud_push", "loggers": ["pubnub", "yalexs"], - "requirements": ["yalexs==1.5.1", "yalexs-ble==2.1.18"] + "requirements": ["yalexs==1.5.1", "yalexs-ble==2.2.0"] } diff --git a/homeassistant/components/yalexs_ble/manifest.json b/homeassistant/components/yalexs_ble/manifest.json index 4822b2d27041e4..67b4e1c929956b 100644 --- a/homeassistant/components/yalexs_ble/manifest.json +++ b/homeassistant/components/yalexs_ble/manifest.json @@ -12,5 +12,5 @@ "dependencies": ["bluetooth_adapters"], "documentation": "https://www.home-assistant.io/integrations/yalexs_ble", "iot_class": "local_push", - "requirements": ["yalexs-ble==2.1.18"] + "requirements": ["yalexs-ble==2.2.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index 26d4911dddaad0..103bcb889ef6b7 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2711,7 +2711,7 @@ yalesmartalarmclient==0.3.9 # homeassistant.components.august # homeassistant.components.yalexs_ble -yalexs-ble==2.1.18 +yalexs-ble==2.2.0 # homeassistant.components.august yalexs==1.5.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 864938446e8d7a..114e164481c3f5 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1990,7 +1990,7 @@ yalesmartalarmclient==0.3.9 # homeassistant.components.august # homeassistant.components.yalexs_ble -yalexs-ble==2.1.18 +yalexs-ble==2.2.0 # homeassistant.components.august yalexs==1.5.1 From 7539cf25beb712d35b778e534671684ac6b8ae3f Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Thu, 13 Jul 2023 19:39:25 +0200 Subject: [PATCH 136/154] Don't require passing identifiers to DeviceRegistry.async_get_device (#96479) * Require keyword arguments to DeviceRegistry.async_get_device * Update tests * Update tests * Don't enforce keyword arguments --- homeassistant/components/airly/__init__.py | 2 +- homeassistant/components/bosch_shc/entity.py | 4 +- homeassistant/components/broadlink/device.py | 4 +- homeassistant/components/deconz/services.py | 3 +- .../components/device_tracker/config_entry.py | 2 +- homeassistant/components/dhcp/__init__.py | 2 +- homeassistant/components/gios/__init__.py | 2 +- homeassistant/components/hassio/__init__.py | 4 +- homeassistant/components/heos/__init__.py | 4 +- .../components/home_plus_control/__init__.py | 2 +- .../homekit_controller/config_flow.py | 2 +- homeassistant/components/hue/v2/device.py | 2 +- homeassistant/components/hue/v2/entity.py | 4 +- homeassistant/components/hue/v2/hue_event.py | 4 +- .../components/ibeacon/coordinator.py | 4 +- .../components/insteon/api/device.py | 4 +- homeassistant/components/kodi/media_player.py | 2 +- homeassistant/components/lcn/__init__.py | 2 +- homeassistant/components/lcn/helpers.py | 6 +- .../components/lutron_caseta/__init__.py | 2 +- homeassistant/components/matter/adapter.py | 2 +- homeassistant/components/nest/__init__.py | 4 +- homeassistant/components/nest/device_info.py | 4 +- homeassistant/components/nest/media_source.py | 2 +- .../components/netatmo/netatmo_entity_base.py | 2 +- homeassistant/components/notion/__init__.py | 8 +- homeassistant/components/onvif/config_flow.py | 2 +- .../components/overkiz/coordinator.py | 4 +- homeassistant/components/sabnzbd/__init__.py | 2 +- homeassistant/components/shelly/__init__.py | 2 - .../components/simplisafe/__init__.py | 2 +- homeassistant/components/tasmota/__init__.py | 4 +- .../components/tasmota/device_trigger.py | 3 +- homeassistant/components/tasmota/discovery.py | 2 +- homeassistant/components/tibber/sensor.py | 4 +- homeassistant/components/unifiprotect/data.py | 2 +- .../components/uptimerobot/__init__.py | 2 +- homeassistant/components/zwave_js/__init__.py | 16 +-- homeassistant/components/zwave_js/api.py | 2 +- .../components/zwave_js/triggers/event.py | 2 +- .../zwave_js/triggers/value_updated.py | 2 +- homeassistant/components/zwave_me/__init__.py | 2 +- homeassistant/helpers/device_registry.py | 17 ++-- .../components/assist_pipeline/test_select.py | 2 +- tests/components/broadlink/test_device.py | 4 +- tests/components/broadlink/test_remote.py | 6 +- tests/components/broadlink/test_sensors.py | 22 ++--- tests/components/broadlink/test_switch.py | 8 +- .../components/bthome/test_device_trigger.py | 6 +- tests/components/canary/test_sensor.py | 4 +- tests/components/daikin/test_init.py | 5 +- tests/components/dlink/test_init.py | 2 +- .../components/dremel_3d_printer/test_init.py | 4 +- tests/components/efergy/test_init.py | 2 +- tests/components/flux_led/test_light.py | 2 +- .../freedompro/test_binary_sensor.py | 2 +- tests/components/freedompro/test_climate.py | 2 +- tests/components/freedompro/test_cover.py | 2 +- tests/components/freedompro/test_fan.py | 2 +- tests/components/freedompro/test_lock.py | 2 +- .../fully_kiosk/test_diagnostics.py | 2 +- tests/components/goalzero/test_init.py | 2 +- tests/components/gogogate2/test_cover.py | 4 +- tests/components/google_mail/test_init.py | 2 +- tests/components/heos/test_media_player.py | 4 +- .../home_plus_control/test_switch.py | 2 +- tests/components/homekit/test_homekit.py | 6 +- tests/components/homekit_controller/common.py | 4 +- .../components/hue/test_device_trigger_v1.py | 6 +- .../components/hue/test_device_trigger_v2.py | 2 +- tests/components/hue/test_sensor_v1.py | 6 +- tests/components/hyperion/test_camera.py | 2 +- tests/components/hyperion/test_light.py | 2 +- tests/components/hyperion/test_switch.py | 2 +- tests/components/ibeacon/test_init.py | 3 +- tests/components/lcn/conftest.py | 2 +- tests/components/lcn/test_device_trigger.py | 6 +- tests/components/lidarr/test_init.py | 2 +- tests/components/lifx/test_light.py | 3 +- tests/components/matter/test_adapter.py | 18 +++- tests/components/mobile_app/test_webhook.py | 4 +- tests/components/motioneye/test_camera.py | 10 +- tests/components/motioneye/test_sensor.py | 2 +- tests/components/motioneye/test_switch.py | 2 +- tests/components/mqtt/test_common.py | 26 ++--- tests/components/mqtt/test_device_tracker.py | 4 +- tests/components/mqtt/test_device_trigger.py | 98 ++++++++++++------- tests/components/mqtt/test_diagnostics.py | 4 +- tests/components/mqtt/test_discovery.py | 20 ++-- tests/components/mqtt/test_init.py | 22 ++--- tests/components/mqtt/test_sensor.py | 2 +- tests/components/mqtt/test_tag.py | 90 +++++++++++------ tests/components/nest/test_device_trigger.py | 6 +- tests/components/nest/test_diagnostics.py | 2 +- tests/components/nest/test_media_source.py | 42 ++++---- .../components/netatmo/test_device_trigger.py | 6 +- .../components/purpleair/test_config_flow.py | 4 +- tests/components/radarr/test_init.py | 2 +- tests/components/rainbird/test_number.py | 2 +- tests/components/renault/__init__.py | 4 +- tests/components/renault/test_diagnostics.py | 4 +- tests/components/renault/test_services.py | 6 +- tests/components/rfxtrx/test_device_action.py | 16 ++- .../components/rfxtrx/test_device_trigger.py | 16 ++- .../risco/test_alarm_control_panel.py | 12 ++- tests/components/risco/test_binary_sensor.py | 16 ++- tests/components/sharkiq/test_vacuum.py | 2 +- .../smartthings/test_binary_sensor.py | 2 +- tests/components/smartthings/test_climate.py | 4 +- tests/components/smartthings/test_cover.py | 2 +- tests/components/smartthings/test_fan.py | 2 +- tests/components/smartthings/test_light.py | 2 +- tests/components/smartthings/test_lock.py | 2 +- tests/components/smartthings/test_sensor.py | 12 +-- tests/components/smartthings/test_switch.py | 2 +- tests/components/steam_online/test_init.py | 2 +- tests/components/steamist/test_init.py | 2 +- tests/components/tasmota/test_common.py | 8 +- .../components/tasmota/test_device_trigger.py | 40 ++++---- tests/components/tasmota/test_discovery.py | 52 +++++----- tests/components/tasmota/test_init.py | 12 +-- tests/components/twinkly/test_light.py | 2 +- tests/components/velbus/test_init.py | 8 +- tests/components/voip/test_devices.py | 12 ++- tests/components/webostv/test_media_player.py | 4 +- .../xiaomi_ble/test_device_trigger.py | 8 +- .../components/yolink/test_device_trigger.py | 2 +- tests/components/youtube/test_init.py | 2 +- tests/components/zha/test_device_action.py | 12 ++- tests/components/zha/test_device_trigger.py | 20 +++- tests/components/zha/test_diagnostics.py | 2 +- tests/components/zha/test_logbook.py | 8 +- tests/components/zwave_js/test_api.py | 4 +- .../components/zwave_js/test_device_action.py | 20 ++-- .../zwave_js/test_device_condition.py | 18 ++-- .../zwave_js/test_device_trigger.py | 54 +++++----- tests/components/zwave_js/test_diagnostics.py | 10 +- tests/components/zwave_js/test_init.py | 4 +- tests/components/zwave_js/test_services.py | 18 ++-- tests/components/zwave_js/test_trigger.py | 6 +- .../zwave_me/test_remove_stale_devices.py | 2 +- tests/helpers/test_device_registry.py | 42 ++++---- tests/helpers/test_entity_platform.py | 12 ++- 143 files changed, 654 insertions(+), 494 deletions(-) diff --git a/homeassistant/components/airly/__init__.py b/homeassistant/components/airly/__init__.py index 85b8b22043a48c..f52bdca4b86084 100644 --- a/homeassistant/components/airly/__init__.py +++ b/homeassistant/components/airly/__init__.py @@ -90,7 +90,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: str(longitude), ), ): - device_entry = device_registry.async_get_device({old_ids}) # type: ignore[arg-type] + device_entry = device_registry.async_get_device(identifiers={old_ids}) # type: ignore[arg-type] if device_entry and entry.entry_id in device_entry.config_entries: new_ids = (DOMAIN, f"{latitude}-{longitude}") device_registry.async_update_device( diff --git a/homeassistant/components/bosch_shc/entity.py b/homeassistant/components/bosch_shc/entity.py index de3e2f9d3eaef7..3cf92a8adcc75b 100644 --- a/homeassistant/components/bosch_shc/entity.py +++ b/homeassistant/components/bosch_shc/entity.py @@ -15,9 +15,7 @@ async def async_remove_devices( ) -> None: """Get item that is removed from session.""" dev_registry = get_dev_reg(hass) - device = dev_registry.async_get_device( - identifiers={(DOMAIN, entity.device_id)}, connections=set() - ) + device = dev_registry.async_get_device(identifiers={(DOMAIN, entity.device_id)}) if device is not None: dev_registry.async_update_device(device.id, remove_config_entry_id=entry_id) diff --git a/homeassistant/components/broadlink/device.py b/homeassistant/components/broadlink/device.py index 87d8cf398fb249..69e1161a65ce52 100644 --- a/homeassistant/components/broadlink/device.py +++ b/homeassistant/components/broadlink/device.py @@ -80,7 +80,9 @@ async def async_update(hass: HomeAssistant, entry: ConfigEntry) -> None: """ device_registry = dr.async_get(hass) assert entry.unique_id - device_entry = device_registry.async_get_device({(DOMAIN, entry.unique_id)}) + device_entry = device_registry.async_get_device( + identifiers={(DOMAIN, entry.unique_id)} + ) assert device_entry device_registry.async_update_device(device_entry.id, name=entry.title) await hass.config_entries.async_reload(entry.entry_id) diff --git a/homeassistant/components/deconz/services.py b/homeassistant/components/deconz/services.py index 5cea4ca3b159d5..bcac6ac1e1dd35 100644 --- a/homeassistant/components/deconz/services.py +++ b/homeassistant/components/deconz/services.py @@ -168,14 +168,13 @@ async def async_remove_orphaned_entries_service(gateway: DeconzGateway) -> None: if gateway.api.config.mac: gateway_host = device_registry.async_get_device( connections={(CONNECTION_NETWORK_MAC, gateway.api.config.mac)}, - identifiers=set(), ) if gateway_host and gateway_host.id in devices_to_be_removed: devices_to_be_removed.remove(gateway_host.id) # Don't remove the Gateway service entry gateway_service = device_registry.async_get_device( - identifiers={(DOMAIN, gateway.api.config.bridge_id)}, connections=set() + identifiers={(DOMAIN, gateway.api.config.bridge_id)} ) if gateway_service and gateway_service.id in devices_to_be_removed: devices_to_be_removed.remove(gateway_service.id) diff --git a/homeassistant/components/device_tracker/config_entry.py b/homeassistant/components/device_tracker/config_entry.py index 286929c534588d..05edfbad91db1f 100644 --- a/homeassistant/components/device_tracker/config_entry.py +++ b/homeassistant/components/device_tracker/config_entry.py @@ -365,7 +365,7 @@ def find_device_entry(self) -> dr.DeviceEntry | None: assert self.mac_address is not None return dr.async_get(self.hass).async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, self.mac_address)} + connections={(dr.CONNECTION_NETWORK_MAC, self.mac_address)} ) async def async_internal_added_to_hass(self) -> None: diff --git a/homeassistant/components/dhcp/__init__.py b/homeassistant/components/dhcp/__init__.py index 4a9f6c2b163dab..9f9ec48f347929 100644 --- a/homeassistant/components/dhcp/__init__.py +++ b/homeassistant/components/dhcp/__init__.py @@ -196,7 +196,7 @@ def async_process_client( dev_reg: DeviceRegistry = async_get(self.hass) if device := dev_reg.async_get_device( - identifiers=set(), connections={(CONNECTION_NETWORK_MAC, uppercase_mac)} + connections={(CONNECTION_NETWORK_MAC, uppercase_mac)} ): for entry_id in device.config_entries: if entry := self.hass.config_entries.async_get_entry(entry_id): diff --git a/homeassistant/components/gios/__init__.py b/homeassistant/components/gios/__init__.py index 213fabc911bf93..2b56a9f6cbb174 100644 --- a/homeassistant/components/gios/__init__.py +++ b/homeassistant/components/gios/__init__.py @@ -37,7 +37,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: # We used to use int in device_entry identifiers, convert this to str. device_registry = dr.async_get(hass) old_ids = (DOMAIN, station_id) - device_entry = device_registry.async_get_device({old_ids}) # type: ignore[arg-type] + device_entry = device_registry.async_get_device(identifiers={old_ids}) # type: ignore[arg-type] if device_entry and entry.entry_id in device_entry.config_entries: new_ids = (DOMAIN, str(station_id)) device_registry.async_update_device(device_entry.id, new_identifiers={new_ids}) diff --git a/homeassistant/components/hassio/__init__.py b/homeassistant/components/hassio/__init__.py index 8c7f86700e7a07..9227b7da617bbf 100644 --- a/homeassistant/components/hassio/__init__.py +++ b/homeassistant/components/hassio/__init__.py @@ -758,7 +758,7 @@ def async_remove_addons_from_dev_reg( ) -> None: """Remove addons from the device registry.""" for addon_slug in addons: - if dev := dev_reg.async_get_device({(DOMAIN, addon_slug)}): + if dev := dev_reg.async_get_device(identifiers={(DOMAIN, addon_slug)}): dev_reg.async_remove_device(dev.id) @@ -855,7 +855,7 @@ async def _async_update_data(self) -> dict[str, Any]: async_remove_addons_from_dev_reg(self.dev_reg, stale_addons) if not self.is_hass_os and ( - dev := self.dev_reg.async_get_device({(DOMAIN, "OS")}) + dev := self.dev_reg.async_get_device(identifiers={(DOMAIN, "OS")}) ): # Remove the OS device if it exists and the installation is not hassos self.dev_reg.async_remove_device(dev.id) diff --git a/homeassistant/components/heos/__init__.py b/homeassistant/components/heos/__init__.py index 7aff107d8c5c6c..c50b70245e3b56 100644 --- a/homeassistant/components/heos/__init__.py +++ b/homeassistant/components/heos/__init__.py @@ -220,7 +220,9 @@ def update_ids(self, mapped_ids: dict[int, int]): # mapped_ids contains the mapped IDs (new:old) for new_id, old_id in mapped_ids.items(): # update device registry - entry = self._device_registry.async_get_device({(DOMAIN, old_id)}) + entry = self._device_registry.async_get_device( + identifiers={(DOMAIN, old_id)} + ) new_identifiers = {(DOMAIN, new_id)} if entry: self._device_registry.async_update_device( diff --git a/homeassistant/components/home_plus_control/__init__.py b/homeassistant/components/home_plus_control/__init__.py index d58086e59ecd2c..007f8895bf042c 100644 --- a/homeassistant/components/home_plus_control/__init__.py +++ b/homeassistant/components/home_plus_control/__init__.py @@ -128,7 +128,7 @@ def _async_update_entities(): entity_uids_to_remove = uids - set(module_data) for uid in entity_uids_to_remove: uids.remove(uid) - device = device_registry.async_get_device({(DOMAIN, uid)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, uid)}) device_registry.async_remove_device(device.id) # Send out signal for new entity addition to Home Assistant diff --git a/homeassistant/components/homekit_controller/config_flow.py b/homeassistant/components/homekit_controller/config_flow.py index f450c38527a60b..988adbd87a7b86 100644 --- a/homeassistant/components/homekit_controller/config_flow.py +++ b/homeassistant/components/homekit_controller/config_flow.py @@ -203,7 +203,7 @@ async def _hkid_is_homekit(self, hkid: str) -> bool: """Determine if the device is a homekit bridge or accessory.""" dev_reg = dr.async_get(self.hass) device = dev_reg.async_get_device( - identifiers=set(), connections={(dr.CONNECTION_NETWORK_MAC, hkid)} + connections={(dr.CONNECTION_NETWORK_MAC, hkid)} ) if device is None: diff --git a/homeassistant/components/hue/v2/device.py b/homeassistant/components/hue/v2/device.py index bc3ce49cb6b4a5..6fed4bc16d1b16 100644 --- a/homeassistant/components/hue/v2/device.py +++ b/homeassistant/components/hue/v2/device.py @@ -58,7 +58,7 @@ def add_device(hue_device: Device) -> dr.DeviceEntry: @callback def remove_device(hue_device_id: str) -> None: """Remove device from registry.""" - if device := dev_reg.async_get_device({(DOMAIN, hue_device_id)}): + if device := dev_reg.async_get_device(identifiers={(DOMAIN, hue_device_id)}): # note: removal of any underlying entities is handled by core dev_reg.async_remove_device(device.id) diff --git a/homeassistant/components/hue/v2/entity.py b/homeassistant/components/hue/v2/entity.py index 5878f01889b8db..ef01b2e4693048 100644 --- a/homeassistant/components/hue/v2/entity.py +++ b/homeassistant/components/hue/v2/entity.py @@ -147,7 +147,9 @@ def _handle_event(self, event_type: EventType, resource: HueResource) -> None: # regular devices are removed automatically by the logic in device.py. if resource.type in (ResourceTypes.ROOM, ResourceTypes.ZONE): dev_reg = async_get_device_registry(self.hass) - if device := dev_reg.async_get_device({(DOMAIN, resource.id)}): + if device := dev_reg.async_get_device( + identifiers={(DOMAIN, resource.id)} + ): dev_reg.async_remove_device(device.id) # cleanup entities that are not strictly device-bound and have the bridge as parent if self.device is None: diff --git a/homeassistant/components/hue/v2/hue_event.py b/homeassistant/components/hue/v2/hue_event.py index e0296bcb4346da..b8521a80af70cc 100644 --- a/homeassistant/components/hue/v2/hue_event.py +++ b/homeassistant/components/hue/v2/hue_event.py @@ -44,7 +44,7 @@ def handle_button_event(evt_type: EventType, hue_resource: Button) -> None: return hue_device = btn_controller.get_device(hue_resource.id) - device = dev_reg.async_get_device({(DOMAIN, hue_device.id)}) + device = dev_reg.async_get_device(identifiers={(DOMAIN, hue_device.id)}) # Fire event data = { @@ -70,7 +70,7 @@ def handle_rotary_event(evt_type: EventType, hue_resource: RelativeRotary) -> No LOGGER.debug("Received relative_rotary event: %s", hue_resource) hue_device = btn_controller.get_device(hue_resource.id) - device = dev_reg.async_get_device({(DOMAIN, hue_device.id)}) + device = dev_reg.async_get_device(identifiers={(DOMAIN, hue_device.id)}) # Fire event data = { diff --git a/homeassistant/components/ibeacon/coordinator.py b/homeassistant/components/ibeacon/coordinator.py index 2e9af4ad9e6e1f..537b4b8f860096 100644 --- a/homeassistant/components/ibeacon/coordinator.py +++ b/homeassistant/components/ibeacon/coordinator.py @@ -200,7 +200,9 @@ def _async_ignore_address(self, address: str) -> None: def _async_purge_untrackable_entities(self, unique_ids: set[str]) -> None: """Remove entities that are no longer trackable.""" for unique_id in unique_ids: - if device := self._dev_reg.async_get_device({(DOMAIN, unique_id)}): + if device := self._dev_reg.async_get_device( + identifiers={(DOMAIN, unique_id)} + ): self._dev_reg.async_remove_device(device.id) self._last_ibeacon_advertisement_by_unique_id.pop(unique_id, None) diff --git a/homeassistant/components/insteon/api/device.py b/homeassistant/components/insteon/api/device.py index bffda96545686b..d48d87fa3475e5 100644 --- a/homeassistant/components/insteon/api/device.py +++ b/homeassistant/components/insteon/api/device.py @@ -43,9 +43,7 @@ def get_insteon_device_from_ha_device(ha_device): async def async_device_name(dev_registry, address): """Get the Insteon device name from a device registry id.""" - ha_device = dev_registry.async_get_device( - identifiers={(DOMAIN, str(address))}, connections=set() - ) + ha_device = dev_registry.async_get_device(identifiers={(DOMAIN, str(address))}) if not ha_device: if device := devices[address]: return f"{device.description} ({device.model})" diff --git a/homeassistant/components/kodi/media_player.py b/homeassistant/components/kodi/media_player.py index af4e5700805124..4a7f30506b25cd 100644 --- a/homeassistant/components/kodi/media_player.py +++ b/homeassistant/components/kodi/media_player.py @@ -422,7 +422,7 @@ async def _on_ws_connected(self): version = (await self._kodi.get_application_properties(["version"]))["version"] sw_version = f"{version['major']}.{version['minor']}" dev_reg = dr.async_get(self.hass) - device = dev_reg.async_get_device({(DOMAIN, self.unique_id)}) + device = dev_reg.async_get_device(identifiers={(DOMAIN, self.unique_id)}) dev_reg.async_update_device(device.id, sw_version=sw_version) self._device_id = device.id diff --git a/homeassistant/components/lcn/__init__.py b/homeassistant/components/lcn/__init__.py index 72b66bc5cf1929..7ef7eb736737c0 100644 --- a/homeassistant/components/lcn/__init__.py +++ b/homeassistant/components/lcn/__init__.py @@ -180,7 +180,7 @@ def async_host_input_received( logical_address.is_group, ) identifiers = {(DOMAIN, generate_unique_id(config_entry.entry_id, address))} - device = device_registry.async_get_device(identifiers, set()) + device = device_registry.async_get_device(identifiers=identifiers) if device is None: return diff --git a/homeassistant/components/lcn/helpers.py b/homeassistant/components/lcn/helpers.py index 776ad116f4ae76..e190b25eded2b1 100644 --- a/homeassistant/components/lcn/helpers.py +++ b/homeassistant/components/lcn/helpers.py @@ -291,7 +291,7 @@ def purge_device_registry( # Find device that references the host. references_host = set() - host_device = device_registry.async_get_device({(DOMAIN, entry_id)}) + host_device = device_registry.async_get_device(identifiers={(DOMAIN, entry_id)}) if host_device is not None: references_host.add(host_device.id) @@ -299,7 +299,9 @@ def purge_device_registry( references_entry_data = set() for device_data in imported_entry_data[CONF_DEVICES]: device_unique_id = generate_unique_id(entry_id, device_data[CONF_ADDRESS]) - device = device_registry.async_get_device({(DOMAIN, device_unique_id)}) + device = device_registry.async_get_device( + identifiers={(DOMAIN, device_unique_id)} + ) if device is not None: references_entry_data.add(device.id) diff --git a/homeassistant/components/lutron_caseta/__init__.py b/homeassistant/components/lutron_caseta/__init__.py index 6d20f29905d243..da2c03745fad46 100644 --- a/homeassistant/components/lutron_caseta/__init__.py +++ b/homeassistant/components/lutron_caseta/__init__.py @@ -142,7 +142,7 @@ def _async_migrator(entity_entry: er.RegistryEntry) -> dict[str, Any] | None: return None sensor_id = unique_id.split("_")[1] new_unique_id = f"occupancygroup_{bridge_unique_id}_{sensor_id}" - if dev_entry := dev_reg.async_get_device({(DOMAIN, unique_id)}): + if dev_entry := dev_reg.async_get_device(identifiers={(DOMAIN, unique_id)}): dev_reg.async_update_device( dev_entry.id, new_identifiers={(DOMAIN, new_unique_id)} ) diff --git a/homeassistant/components/matter/adapter.py b/homeassistant/components/matter/adapter.py index 8e76706b7fdb8b..52b8e905b4b6ff 100644 --- a/homeassistant/components/matter/adapter.py +++ b/homeassistant/components/matter/adapter.py @@ -80,7 +80,7 @@ def endpoint_removed_callback(event: EventType, data: dict[str, int]) -> None: node.endpoints[data["endpoint_id"]], ) identifier = (DOMAIN, f"{ID_TYPE_DEVICE_ID}_{node_device_id}") - if device := device_registry.async_get_device({identifier}): + if device := device_registry.async_get_device(identifiers={identifier}): device_registry.async_remove_device(device.id) def node_removed_callback(event: EventType, node_id: int) -> None: diff --git a/homeassistant/components/nest/__init__.py b/homeassistant/components/nest/__init__.py index 5f2a0b0bffd6c1..e85073061c27d8 100644 --- a/homeassistant/components/nest/__init__.py +++ b/homeassistant/components/nest/__init__.py @@ -152,7 +152,9 @@ async def async_handle_event(self, event_message: EventMessage) -> None: return _LOGGER.debug("Event Update %s", events.keys()) device_registry = dr.async_get(self._hass) - device_entry = device_registry.async_get_device({(DOMAIN, device_id)}) + device_entry = device_registry.async_get_device( + identifiers={(DOMAIN, device_id)} + ) if not device_entry: return for api_event_type, image_event in events.items(): diff --git a/homeassistant/components/nest/device_info.py b/homeassistant/components/nest/device_info.py index e269b76fcc4be5..891365655def66 100644 --- a/homeassistant/components/nest/device_info.py +++ b/homeassistant/components/nest/device_info.py @@ -100,6 +100,8 @@ def async_nest_devices_by_device_id(hass: HomeAssistant) -> Mapping[str, Device] device_registry = dr.async_get(hass) devices = {} for nest_device_id, device in async_nest_devices(hass).items(): - if device_entry := device_registry.async_get_device({(DOMAIN, nest_device_id)}): + if device_entry := device_registry.async_get_device( + identifiers={(DOMAIN, nest_device_id)} + ): devices[device_entry.id] = device return devices diff --git a/homeassistant/components/nest/media_source.py b/homeassistant/components/nest/media_source.py index d9478a99316ce9..ba2faaeaae5ce0 100644 --- a/homeassistant/components/nest/media_source.py +++ b/homeassistant/components/nest/media_source.py @@ -244,7 +244,7 @@ async def _get_devices(self) -> Mapping[str, str]: devices = {} for device in device_manager.devices.values(): if device_entry := device_registry.async_get_device( - {(DOMAIN, device.name)} + identifiers={(DOMAIN, device.name)} ): devices[device.name] = device_entry.id return devices diff --git a/homeassistant/components/netatmo/netatmo_entity_base.py b/homeassistant/components/netatmo/netatmo_entity_base.py index 12798c164f834e..ff6783ecaa3e5d 100644 --- a/homeassistant/components/netatmo/netatmo_entity_base.py +++ b/homeassistant/components/netatmo/netatmo_entity_base.py @@ -70,7 +70,7 @@ async def async_added_to_hass(self) -> None: await self.data_handler.unsubscribe(signal_name, None) registry = dr.async_get(self.hass) - if device := registry.async_get_device({(DOMAIN, self._id)}): + if device := registry.async_get_device(identifiers={(DOMAIN, self._id)}): self.hass.data[DOMAIN][DATA_DEVICE_IDS][self._id] = device.id self.async_update_callback() diff --git a/homeassistant/components/notion/__init__.py b/homeassistant/components/notion/__init__.py index ad228f08a4b178..258f14056ca6bb 100644 --- a/homeassistant/components/notion/__init__.py +++ b/homeassistant/components/notion/__init__.py @@ -339,9 +339,13 @@ def _async_update_bridge_id(self) -> None: self._bridge_id = sensor.bridge.id device_registry = dr.async_get(self.hass) - this_device = device_registry.async_get_device({(DOMAIN, sensor.hardware_id)}) + this_device = device_registry.async_get_device( + identifiers={(DOMAIN, sensor.hardware_id)} + ) bridge = self.coordinator.data.bridges[self._bridge_id] - bridge_device = device_registry.async_get_device({(DOMAIN, bridge.hardware_id)}) + bridge_device = device_registry.async_get_device( + identifiers={(DOMAIN, bridge.hardware_id)} + ) if not bridge_device or not this_device: return diff --git a/homeassistant/components/onvif/config_flow.py b/homeassistant/components/onvif/config_flow.py index c1df94f5f8383b..842fe4298cfc53 100644 --- a/homeassistant/components/onvif/config_flow.py +++ b/homeassistant/components/onvif/config_flow.py @@ -171,7 +171,7 @@ async def async_step_dhcp(self, discovery_info: dhcp.DhcpServiceInfo) -> FlowRes registry = dr.async_get(self.hass) if not ( device := registry.async_get_device( - identifiers=set(), connections={(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) ): return self.async_abort(reason="no_devices_found") diff --git a/homeassistant/components/overkiz/coordinator.py b/homeassistant/components/overkiz/coordinator.py index b27051b1492d2d..7c9cab5f181de4 100644 --- a/homeassistant/components/overkiz/coordinator.py +++ b/homeassistant/components/overkiz/coordinator.py @@ -178,7 +178,9 @@ async def on_device_removed( base_device_url = event.device_url.split("#")[0] registry = dr.async_get(coordinator.hass) - if registered_device := registry.async_get_device({(DOMAIN, base_device_url)}): + if registered_device := registry.async_get_device( + identifiers={(DOMAIN, base_device_url)} + ): registry.async_remove_device(registered_device.id) if event.device_url: diff --git a/homeassistant/components/sabnzbd/__init__.py b/homeassistant/components/sabnzbd/__init__.py index 2e345905d50284..babdbc573bd14b 100644 --- a/homeassistant/components/sabnzbd/__init__.py +++ b/homeassistant/components/sabnzbd/__init__.py @@ -127,7 +127,7 @@ def async_get_entry_id_for_service_call(hass: HomeAssistant, call: ServiceCall) def update_device_identifiers(hass: HomeAssistant, entry: ConfigEntry): """Update device identifiers to new identifiers.""" device_registry = async_get(hass) - device_entry = device_registry.async_get_device({(DOMAIN, DOMAIN)}) + device_entry = device_registry.async_get_device(identifiers={(DOMAIN, DOMAIN)}) if device_entry and entry.entry_id in device_entry.config_entries: new_identifiers = {(DOMAIN, entry.entry_id)} _LOGGER.debug( diff --git a/homeassistant/components/shelly/__init__.py b/homeassistant/components/shelly/__init__.py index 69959453a78403..8f08aab8d3072f 100644 --- a/homeassistant/components/shelly/__init__.py +++ b/homeassistant/components/shelly/__init__.py @@ -143,7 +143,6 @@ async def _async_setup_block_entry(hass: HomeAssistant, entry: ConfigEntry) -> b device_entry = None if entry.unique_id is not None: device_entry = dev_reg.async_get_device( - identifiers=set(), connections={(CONNECTION_NETWORK_MAC, format_mac(entry.unique_id))}, ) # https://github.com/home-assistant/core/pull/48076 @@ -227,7 +226,6 @@ async def _async_setup_rpc_entry(hass: HomeAssistant, entry: ConfigEntry) -> boo device_entry = None if entry.unique_id is not None: device_entry = dev_reg.async_get_device( - identifiers=set(), connections={(CONNECTION_NETWORK_MAC, format_mac(entry.unique_id))}, ) # https://github.com/home-assistant/core/pull/48076 diff --git a/homeassistant/components/simplisafe/__init__.py b/homeassistant/components/simplisafe/__init__.py index 17fc6f3cc4de4e..dec1b35d34678b 100644 --- a/homeassistant/components/simplisafe/__init__.py +++ b/homeassistant/components/simplisafe/__init__.py @@ -268,7 +268,7 @@ def _async_register_base_station( # Check for an old system ID format and remove it: if old_base_station := device_registry.async_get_device( - {(DOMAIN, system.system_id)} # type: ignore[arg-type] + identifiers={(DOMAIN, system.system_id)} # type: ignore[arg-type] ): # Update the new base station with any properties the user might have configured # on the old base station: diff --git a/homeassistant/components/tasmota/__init__.py b/homeassistant/components/tasmota/__init__.py index 2123ee74f1b656..7d4331f0d408eb 100644 --- a/homeassistant/components/tasmota/__init__.py +++ b/homeassistant/components/tasmota/__init__.py @@ -119,7 +119,9 @@ async def _remove_device( device_registry: DeviceRegistry, ) -> None: """Remove a discovered Tasmota device.""" - device = device_registry.async_get_device(set(), {(CONNECTION_NETWORK_MAC, mac)}) + device = device_registry.async_get_device( + connections={(CONNECTION_NETWORK_MAC, mac)} + ) if device is None or config_entry.entry_id not in device.config_entries: return diff --git a/homeassistant/components/tasmota/device_trigger.py b/homeassistant/components/tasmota/device_trigger.py index 49caf30b010ac1..f01cdddb1db4b8 100644 --- a/homeassistant/components/tasmota/device_trigger.py +++ b/homeassistant/components/tasmota/device_trigger.py @@ -223,8 +223,7 @@ async def discovery_update(trigger_config: TasmotaTriggerConfig) -> None: device_registry = dr.async_get(hass) device = device_registry.async_get_device( - set(), - {(CONNECTION_NETWORK_MAC, tasmota_trigger.cfg.mac)}, + connections={(CONNECTION_NETWORK_MAC, tasmota_trigger.cfg.mac)}, ) if device is None: diff --git a/homeassistant/components/tasmota/discovery.py b/homeassistant/components/tasmota/discovery.py index b490b4c724c0cf..70cedd9dd3d242 100644 --- a/homeassistant/components/tasmota/discovery.py +++ b/homeassistant/components/tasmota/discovery.py @@ -302,7 +302,7 @@ async def async_sensors_discovered( device_registry = dr.async_get(hass) entity_registry = er.async_get(hass) device = device_registry.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) if device is None: diff --git a/homeassistant/components/tibber/sensor.py b/homeassistant/components/tibber/sensor.py index 242c2179a05cc8..996490282d5256 100644 --- a/homeassistant/components/tibber/sensor.py +++ b/homeassistant/components/tibber/sensor.py @@ -289,7 +289,9 @@ async def async_setup_entry( ) # migrate to new device ids - device_entry = device_registry.async_get_device({(TIBBER_DOMAIN, old_id)}) + device_entry = device_registry.async_get_device( + identifiers={(TIBBER_DOMAIN, old_id)} + ) if device_entry and entry.entry_id in device_entry.config_entries: device_registry.async_update_device( device_entry.id, new_identifiers={(TIBBER_DOMAIN, home.home_id)} diff --git a/homeassistant/components/unifiprotect/data.py b/homeassistant/components/unifiprotect/data.py index 88c500f18fd006..3e4410fa41ad1e 100644 --- a/homeassistant/components/unifiprotect/data.py +++ b/homeassistant/components/unifiprotect/data.py @@ -178,7 +178,7 @@ def _async_add_device(self, device: ProtectAdoptableDeviceModel) -> None: def _async_remove_device(self, device: ProtectAdoptableDeviceModel) -> None: registry = dr.async_get(self._hass) device_entry = registry.async_get_device( - identifiers=set(), connections={(dr.CONNECTION_NETWORK_MAC, device.mac)} + connections={(dr.CONNECTION_NETWORK_MAC, device.mac)} ) if device_entry: _LOGGER.debug("Device removed: %s", device.id) diff --git a/homeassistant/components/uptimerobot/__init__.py b/homeassistant/components/uptimerobot/__init__.py index 359e4c6831a9d0..3cb119837d72bd 100644 --- a/homeassistant/components/uptimerobot/__init__.py +++ b/homeassistant/components/uptimerobot/__init__.py @@ -100,7 +100,7 @@ async def _async_update_data(self) -> list[UptimeRobotMonitor]: if stale_monitors := current_monitors - new_monitors: for monitor_id in stale_monitors: if device := self._device_registry.async_get_device( - {(DOMAIN, monitor_id)} + identifiers={(DOMAIN, monitor_id)} ): self._device_registry.async_remove_device(device.id) diff --git a/homeassistant/components/zwave_js/__init__.py b/homeassistant/components/zwave_js/__init__.py index 8c1dd9b2197fa2..7ff351893b1bae 100644 --- a/homeassistant/components/zwave_js/__init__.py +++ b/homeassistant/components/zwave_js/__init__.py @@ -254,7 +254,7 @@ async def setup(self, driver: Driver) -> None: self.dev_reg, self.config_entry.entry_id ) known_devices = [ - self.dev_reg.async_get_device({get_device_id(driver, node)}) + self.dev_reg.async_get_device(identifiers={get_device_id(driver, node)}) for node in controller.nodes.values() ] @@ -401,7 +401,7 @@ def async_on_node_removed(self, event: dict) -> None: replaced: bool = event.get("replaced", False) # grab device in device registry attached to this node dev_id = get_device_id(self.driver_events.driver, node) - device = self.dev_reg.async_get_device({dev_id}) + device = self.dev_reg.async_get_device(identifiers={dev_id}) # We assert because we know the device exists assert device if replaced: @@ -424,7 +424,7 @@ def register_node_in_dev_reg(self, node: ZwaveNode) -> dr.DeviceEntry: driver = self.driver_events.driver device_id = get_device_id(driver, node) device_id_ext = get_device_id_ext(driver, node) - device = self.dev_reg.async_get_device({device_id}) + device = self.dev_reg.async_get_device(identifiers={device_id}) via_device_id = None controller = driver.controller # Get the controller node device ID if this node is not the controller @@ -610,7 +610,7 @@ async def async_on_value_added( ) if ( not value.node.ready - or not (device := self.dev_reg.async_get_device({device_id})) + or not (device := self.dev_reg.async_get_device(identifiers={device_id})) or value.value_id in self.controller_events.discovered_value_ids[device.id] ): return @@ -632,7 +632,7 @@ def async_on_value_notification(self, notification: ValueNotification) -> None: """Relay stateless value notification events from Z-Wave nodes to hass.""" driver = self.controller_events.driver_events.driver device = self.dev_reg.async_get_device( - {get_device_id(driver, notification.node)} + identifiers={get_device_id(driver, notification.node)} ) # We assert because we know the device exists assert device @@ -671,7 +671,7 @@ def async_on_notification(self, event: dict[str, Any]) -> None: "notification" ] device = self.dev_reg.async_get_device( - {get_device_id(driver, notification.node)} + identifiers={get_device_id(driver, notification.node)} ) # We assert because we know the device exists assert device @@ -741,7 +741,9 @@ def async_on_value_updated_fire_event( driver = self.controller_events.driver_events.driver disc_info = value_updates_disc_info[value.value_id] - device = self.dev_reg.async_get_device({get_device_id(driver, value.node)}) + device = self.dev_reg.async_get_device( + identifiers={get_device_id(driver, value.node)} + ) # We assert because we know the device exists assert device diff --git a/homeassistant/components/zwave_js/api.py b/homeassistant/components/zwave_js/api.py index 867405530abbb7..5fc7da68e99c4f 100644 --- a/homeassistant/components/zwave_js/api.py +++ b/homeassistant/components/zwave_js/api.py @@ -2347,7 +2347,7 @@ def _convert_node_to_device_id(node: Node) -> str: """Convert a node to a device id.""" driver = node.client.driver assert driver - device = dev_reg.async_get_device({get_device_id(driver, node)}) + device = dev_reg.async_get_device(identifiers={get_device_id(driver, node)}) assert device return device.id diff --git a/homeassistant/components/zwave_js/triggers/event.py b/homeassistant/components/zwave_js/triggers/event.py index 33cb59d8505154..edc10d4a16e0e1 100644 --- a/homeassistant/components/zwave_js/triggers/event.py +++ b/homeassistant/components/zwave_js/triggers/event.py @@ -232,7 +232,7 @@ def _create_zwave_listeners() -> None: assert driver is not None # The node comes from the driver. drivers.add(driver) device_identifier = get_device_id(driver, node) - device = dev_reg.async_get_device({device_identifier}) + device = dev_reg.async_get_device(identifiers={device_identifier}) assert device # We need to store the device for the callback unsubs.append( diff --git a/homeassistant/components/zwave_js/triggers/value_updated.py b/homeassistant/components/zwave_js/triggers/value_updated.py index 52ecc0a7742298..c44a0c6336ae72 100644 --- a/homeassistant/components/zwave_js/triggers/value_updated.py +++ b/homeassistant/components/zwave_js/triggers/value_updated.py @@ -179,7 +179,7 @@ def _create_zwave_listeners() -> None: assert driver is not None # The node comes from the driver. drivers.add(driver) device_identifier = get_device_id(driver, node) - device = dev_reg.async_get_device({device_identifier}) + device = dev_reg.async_get_device(identifiers={device_identifier}) assert device value_id = get_value_id_str( node, command_class, property_, endpoint, property_key diff --git a/homeassistant/components/zwave_me/__init__.py b/homeassistant/components/zwave_me/__init__.py index 1740820d0ba52f..86cebe811809bc 100644 --- a/homeassistant/components/zwave_me/__init__.py +++ b/homeassistant/components/zwave_me/__init__.py @@ -96,7 +96,7 @@ def remove_stale_devices(self, registry: dr.DeviceRegistry): """Remove old-format devices in the registry.""" for device_id in self.device_ids: device = registry.async_get_device( - {(DOMAIN, f"{self.config.unique_id}-{device_id}")} + identifiers={(DOMAIN, f"{self.config.unique_id}-{device_id}")} ) if device is not None: registry.async_remove_device(device.id) diff --git a/homeassistant/helpers/device_registry.py b/homeassistant/helpers/device_registry.py index 7df01fc8fd2b1c..79b4eac68d55ca 100644 --- a/homeassistant/helpers/device_registry.py +++ b/homeassistant/helpers/device_registry.py @@ -272,13 +272,14 @@ def __delitem__(self, key: str) -> None: def get_entry( self, - identifiers: set[tuple[str, str]], + identifiers: set[tuple[str, str]] | None, connections: set[tuple[str, str]] | None, ) -> _EntryTypeT | None: """Get entry from identifiers or connections.""" - for identifier in identifiers: - if identifier in self._identifiers: - return self._identifiers[identifier] + if identifiers: + for identifier in identifiers: + if identifier in self._identifiers: + return self._identifiers[identifier] if not connections: return None for connection in _normalize_connections(connections): @@ -317,7 +318,7 @@ def async_get(self, device_id: str) -> DeviceEntry | None: @callback def async_get_device( self, - identifiers: set[tuple[str, str]], + identifiers: set[tuple[str, str]] | None = None, connections: set[tuple[str, str]] | None = None, ) -> DeviceEntry | None: """Check if device is registered.""" @@ -326,7 +327,7 @@ def async_get_device( def _async_get_deleted_device( self, identifiers: set[tuple[str, str]], - connections: set[tuple[str, str]] | None, + connections: set[tuple[str, str]], ) -> DeletedDeviceEntry | None: """Check if device is deleted.""" return self.deleted_devices.get_entry(identifiers, connections) @@ -365,7 +366,7 @@ def async_get_or_create( else: connections = _normalize_connections(connections) - device = self.async_get_device(identifiers, connections) + device = self.async_get_device(identifiers=identifiers, connections=connections) if device is None: deleted_device = self._async_get_deleted_device(identifiers, connections) @@ -388,7 +389,7 @@ def async_get_or_create( name = default_name if via_device is not None: - via = self.async_get_device({via_device}) + via = self.async_get_device(identifiers={via_device}) via_device_id: str | UndefinedType = via.id if via else UNDEFINED else: via_device_id = UNDEFINED diff --git a/tests/components/assist_pipeline/test_select.py b/tests/components/assist_pipeline/test_select.py index bb9c4d45a32abc..29e6f9a8f31d20 100644 --- a/tests/components/assist_pipeline/test_select.py +++ b/tests/components/assist_pipeline/test_select.py @@ -102,7 +102,7 @@ async def test_select_entity_registering_device( ) -> None: """Test entity registering as an assist device.""" dev_reg = dr.async_get(hass) - device = dev_reg.async_get_device({("test", "test")}) + device = dev_reg.async_get_device(identifiers={("test", "test")}) assert device is not None # Test device is registered diff --git a/tests/components/broadlink/test_device.py b/tests/components/broadlink/test_device.py index bcbc0fc9cdee0d..b97911262ef7fb 100644 --- a/tests/components/broadlink/test_device.py +++ b/tests/components/broadlink/test_device.py @@ -260,7 +260,7 @@ async def test_device_setup_registry( assert len(device_registry.devices) == 1 device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) assert device_entry.identifiers == {(DOMAIN, device.mac)} assert device_entry.name == device.name @@ -349,7 +349,7 @@ async def test_device_update_listener( await hass.async_block_till_done() device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) assert device_entry.name == "New Name" for entry in er.async_entries_for_device(entity_registry, device_entry.id): diff --git a/tests/components/broadlink/test_remote.py b/tests/components/broadlink/test_remote.py index 00048e09577f76..5665f7529d5ea4 100644 --- a/tests/components/broadlink/test_remote.py +++ b/tests/components/broadlink/test_remote.py @@ -33,7 +33,7 @@ async def test_remote_setup_works( mock_setup = await device.setup_entry(hass) device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) remotes = [entry for entry in entries if entry.domain == Platform.REMOTE] @@ -58,7 +58,7 @@ async def test_remote_send_command( mock_setup = await device.setup_entry(hass) device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) remotes = [entry for entry in entries if entry.domain == Platform.REMOTE] @@ -87,7 +87,7 @@ async def test_remote_turn_off_turn_on( mock_setup = await device.setup_entry(hass) device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) remotes = [entry for entry in entries if entry.domain == Platform.REMOTE] diff --git a/tests/components/broadlink/test_sensors.py b/tests/components/broadlink/test_sensors.py index f1802ce51aa3f3..e00350b7627c99 100644 --- a/tests/components/broadlink/test_sensors.py +++ b/tests/components/broadlink/test_sensors.py @@ -34,7 +34,7 @@ async def test_a1_sensor_setup( assert mock_api.check_sensors_raw.call_count == 1 device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) sensors = [entry for entry in entries if entry.domain == Platform.SENSOR] @@ -75,7 +75,7 @@ async def test_a1_sensor_update( mock_setup = await device.setup_entry(hass, mock_api=mock_api) device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) sensors = [entry for entry in entries if entry.domain == Platform.SENSOR] @@ -121,7 +121,7 @@ async def test_rm_pro_sensor_setup( assert mock_api.check_sensors.call_count == 1 device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) sensors = [entry for entry in entries if entry.domain == Platform.SENSOR] @@ -150,7 +150,7 @@ async def test_rm_pro_sensor_update( mock_setup = await device.setup_entry(hass, mock_api=mock_api) device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) sensors = [entry for entry in entries if entry.domain == Platform.SENSOR] @@ -186,7 +186,7 @@ async def test_rm_pro_filter_crazy_temperature( mock_setup = await device.setup_entry(hass, mock_api=mock_api) device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) sensors = [entry for entry in entries if entry.domain == Platform.SENSOR] @@ -220,7 +220,7 @@ async def test_rm_mini3_no_sensor( assert mock_api.check_sensors.call_count <= 1 device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) sensors = [entry for entry in entries if entry.domain == Platform.SENSOR] @@ -241,7 +241,7 @@ async def test_rm4_pro_hts2_sensor_setup( assert mock_api.check_sensors.call_count == 1 device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) sensors = [entry for entry in entries if entry.domain == Platform.SENSOR] @@ -273,7 +273,7 @@ async def test_rm4_pro_hts2_sensor_update( mock_setup = await device.setup_entry(hass, mock_api=mock_api) device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) sensors = [entry for entry in entries if entry.domain == Platform.SENSOR] @@ -310,7 +310,7 @@ async def test_rm4_pro_no_sensor( assert mock_api.check_sensors.call_count <= 1 device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) sensors = {entry for entry in entries if entry.domain == Platform.SENSOR} @@ -341,7 +341,7 @@ async def test_scb1e_sensor_setup( assert mock_api.get_state.call_count == 1 device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) sensors = [entry for entry in entries if entry.domain == Platform.SENSOR] @@ -392,7 +392,7 @@ async def test_scb1e_sensor_update( mock_setup = await device.setup_entry(hass, mock_api=mock_api) device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) sensors = [entry for entry in entries if entry.domain == Platform.SENSOR] diff --git a/tests/components/broadlink/test_switch.py b/tests/components/broadlink/test_switch.py index 35edfb977a9b8a..93bad2db29567e 100644 --- a/tests/components/broadlink/test_switch.py +++ b/tests/components/broadlink/test_switch.py @@ -22,7 +22,7 @@ async def test_switch_setup_works( mock_setup = await device.setup_entry(hass) device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) switches = [entry for entry in entries if entry.domain == Platform.SWITCH] @@ -46,7 +46,7 @@ async def test_switch_turn_off_turn_on( mock_setup = await device.setup_entry(hass) device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) switches = [entry for entry in entries if entry.domain == Platform.SWITCH] @@ -82,7 +82,7 @@ async def test_slots_switch_setup_works( mock_setup = await device.setup_entry(hass) device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) switches = [entry for entry in entries if entry.domain == Platform.SWITCH] @@ -107,7 +107,7 @@ async def test_slots_switch_turn_off_turn_on( mock_setup = await device.setup_entry(hass) device_entry = device_registry.async_get_device( - {(DOMAIN, mock_setup.entry.unique_id)} + identifiers={(DOMAIN, mock_setup.entry.unique_id)} ) entries = er.async_entries_for_device(entity_registry, device_entry.id) switches = [entry for entry in entries if entry.domain == Platform.SWITCH] diff --git a/tests/components/bthome/test_device_trigger.py b/tests/components/bthome/test_device_trigger.py index 348894346bb29d..85169e80394b06 100644 --- a/tests/components/bthome/test_device_trigger.py +++ b/tests/components/bthome/test_device_trigger.py @@ -112,7 +112,7 @@ async def test_get_triggers_button(hass: HomeAssistant) -> None: assert len(events) == 1 dev_reg = async_get_dev_reg(hass) - device = dev_reg.async_get_device({get_device_id(mac)}) + device = dev_reg.async_get_device(identifiers={get_device_id(mac)}) assert device expected_trigger = { CONF_PLATFORM: "device", @@ -148,7 +148,7 @@ async def test_get_triggers_dimmer(hass: HomeAssistant) -> None: assert len(events) == 1 dev_reg = async_get_dev_reg(hass) - device = dev_reg.async_get_device({get_device_id(mac)}) + device = dev_reg.async_get_device(identifiers={get_device_id(mac)}) assert device expected_trigger = { CONF_PLATFORM: "device", @@ -243,7 +243,7 @@ async def test_if_fires_on_motion_detected(hass: HomeAssistant, calls) -> None: await hass.async_block_till_done() dev_reg = async_get_dev_reg(hass) - device = dev_reg.async_get_device({get_device_id(mac)}) + device = dev_reg.async_get_device(identifiers={get_device_id(mac)}) device_id = device.id assert await async_setup_component( diff --git a/tests/components/canary/test_sensor.py b/tests/components/canary/test_sensor.py index 81718fe277cb69..f8e262896916d8 100644 --- a/tests/components/canary/test_sensor.py +++ b/tests/components/canary/test_sensor.py @@ -88,7 +88,7 @@ async def test_sensors_pro( assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == data[2] assert state.state == data[1] - device = device_registry.async_get_device({(DOMAIN, "20")}) + device = device_registry.async_get_device(identifiers={(DOMAIN, "20")}) assert device assert device.manufacturer == MANUFACTURER assert device.name == "Dining Room" @@ -208,7 +208,7 @@ async def test_sensors_flex( assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == data[2] assert state.state == data[1] - device = device_registry.async_get_device({(DOMAIN, "20")}) + device = device_registry.async_get_device(identifiers={(DOMAIN, "20")}) assert device assert device.manufacturer == MANUFACTURER assert device.name == "Dining Room" diff --git a/tests/components/daikin/test_init.py b/tests/components/daikin/test_init.py index 8145a7a1e99b7a..a6a58b4fb39303 100644 --- a/tests/components/daikin/test_init.py +++ b/tests/components/daikin/test_init.py @@ -67,7 +67,7 @@ async def test_unique_id_migrate(hass: HomeAssistant, mock_daikin) -> None: assert config_entry.unique_id == HOST - assert device_registry.async_get_device({}, {(KEY_MAC, HOST)}).name is None + assert device_registry.async_get_device(connections={(KEY_MAC, HOST)}).name is None entity = entity_registry.async_get("climate.daikin_127_0_0_1") assert entity.unique_id == HOST @@ -86,7 +86,8 @@ async def test_unique_id_migrate(hass: HomeAssistant, mock_daikin) -> None: assert config_entry.unique_id == MAC assert ( - device_registry.async_get_device({}, {(KEY_MAC, MAC)}).name == "DaikinAP00000" + device_registry.async_get_device(connections={(KEY_MAC, MAC)}).name + == "DaikinAP00000" ) entity = entity_registry.async_get("climate.daikin_127_0_0_1") diff --git a/tests/components/dlink/test_init.py b/tests/components/dlink/test_init.py index c931fed78e2ab3..dbd4cef0139a7c 100644 --- a/tests/components/dlink/test_init.py +++ b/tests/components/dlink/test_init.py @@ -66,7 +66,7 @@ async def test_device_info( entry = hass.config_entries.async_entries(DOMAIN)[0] device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, entry.entry_id)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, entry.entry_id)}) assert device.connections == {("mac", "aa:bb:cc:dd:ee:ff")} assert device.identifiers == {(DOMAIN, entry.entry_id)} diff --git a/tests/components/dremel_3d_printer/test_init.py b/tests/components/dremel_3d_printer/test_init.py index a77c6159927b20..2740b638316f5f 100644 --- a/tests/components/dremel_3d_printer/test_init.py +++ b/tests/components/dremel_3d_printer/test_init.py @@ -80,7 +80,9 @@ async def test_device_info( await hass.config_entries.async_setup(config_entry.entry_id) assert await async_setup_component(hass, DOMAIN, {}) device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, config_entry.unique_id)}) + device = device_registry.async_get_device( + identifiers={(DOMAIN, config_entry.unique_id)} + ) assert device.manufacturer == "Dremel" assert device.model == "3D45" diff --git a/tests/components/efergy/test_init.py b/tests/components/efergy/test_init.py index 723fd0d6332e90..e82d661592350c 100644 --- a/tests/components/efergy/test_init.py +++ b/tests/components/efergy/test_init.py @@ -53,7 +53,7 @@ async def test_device_info( entry = await setup_platform(hass, aioclient_mock, SENSOR_DOMAIN) device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, entry.entry_id)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, entry.entry_id)}) assert device.configuration_url == "https://engage.efergy.com/user/login" assert device.connections == {("mac", "ff:ff:ff:ff:ff:ff")} diff --git a/tests/components/flux_led/test_light.py b/tests/components/flux_led/test_light.py index 2216e4df737faa..171112c90975eb 100644 --- a/tests/components/flux_led/test_light.py +++ b/tests/components/flux_led/test_light.py @@ -182,7 +182,7 @@ async def test_light_device_registry( device_registry = dr.async_get(hass) device = device_registry.async_get_device( - identifiers={}, connections={(dr.CONNECTION_NETWORK_MAC, MAC_ADDRESS)} + connections={(dr.CONNECTION_NETWORK_MAC, MAC_ADDRESS)} ) assert device.sw_version == str(sw_version) assert device.model == model diff --git a/tests/components/freedompro/test_binary_sensor.py b/tests/components/freedompro/test_binary_sensor.py index 8a3605782a25a8..5efa5ca96f7edb 100644 --- a/tests/components/freedompro/test_binary_sensor.py +++ b/tests/components/freedompro/test_binary_sensor.py @@ -56,7 +56,7 @@ async def test_binary_sensor_get_state( registry = er.async_get(hass) registry_device = dr.async_get(hass) - device = registry_device.async_get_device({("freedompro", uid)}) + device = registry_device.async_get_device(identifiers={("freedompro", uid)}) assert device is not None assert device.identifiers == {("freedompro", uid)} assert device.manufacturer == "Freedompro" diff --git a/tests/components/freedompro/test_climate.py b/tests/components/freedompro/test_climate.py index ae7c39ed4baf0f..41a550b3c508d6 100644 --- a/tests/components/freedompro/test_climate.py +++ b/tests/components/freedompro/test_climate.py @@ -33,7 +33,7 @@ async def test_climate_get_state(hass: HomeAssistant, init_integration) -> None: entity_registry = er.async_get(hass) device_registry = dr.async_get(hass) - device = device_registry.async_get_device({("freedompro", uid)}) + device = device_registry.async_get_device(identifiers={("freedompro", uid)}) assert device is not None assert device.identifiers == {("freedompro", uid)} assert device.manufacturer == "Freedompro" diff --git a/tests/components/freedompro/test_cover.py b/tests/components/freedompro/test_cover.py index b29e6499fec3e6..af54b1c2793a2a 100644 --- a/tests/components/freedompro/test_cover.py +++ b/tests/components/freedompro/test_cover.py @@ -47,7 +47,7 @@ async def test_cover_get_state( registry = er.async_get(hass) registry_device = dr.async_get(hass) - device = registry_device.async_get_device({("freedompro", uid)}) + device = registry_device.async_get_device(identifiers={("freedompro", uid)}) assert device is not None assert device.identifiers == {("freedompro", uid)} assert device.manufacturer == "Freedompro" diff --git a/tests/components/freedompro/test_fan.py b/tests/components/freedompro/test_fan.py index 159b495e0f8e3f..b5acf3e496ac81 100644 --- a/tests/components/freedompro/test_fan.py +++ b/tests/components/freedompro/test_fan.py @@ -27,7 +27,7 @@ async def test_fan_get_state(hass: HomeAssistant, init_integration) -> None: registry = er.async_get(hass) registry_device = dr.async_get(hass) - device = registry_device.async_get_device({("freedompro", uid)}) + device = registry_device.async_get_device(identifiers={("freedompro", uid)}) assert device is not None assert device.identifiers == {("freedompro", uid)} assert device.manufacturer == "Freedompro" diff --git a/tests/components/freedompro/test_lock.py b/tests/components/freedompro/test_lock.py index ae208194d2a256..c9f75e6b59416a 100644 --- a/tests/components/freedompro/test_lock.py +++ b/tests/components/freedompro/test_lock.py @@ -26,7 +26,7 @@ async def test_lock_get_state(hass: HomeAssistant, init_integration) -> None: registry = er.async_get(hass) registry_device = dr.async_get(hass) - device = registry_device.async_get_device({("freedompro", uid)}) + device = registry_device.async_get_device(identifiers={("freedompro", uid)}) assert device is not None assert device.identifiers == {("freedompro", uid)} assert device.manufacturer == "Freedompro" diff --git a/tests/components/fully_kiosk/test_diagnostics.py b/tests/components/fully_kiosk/test_diagnostics.py index ebd4a028f8c059..b1b30bda669b94 100644 --- a/tests/components/fully_kiosk/test_diagnostics.py +++ b/tests/components/fully_kiosk/test_diagnostics.py @@ -24,7 +24,7 @@ async def test_diagnostics( """Test Fully Kiosk diagnostics.""" device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, "abcdef-123456")}) + device = device_registry.async_get_device(identifiers={(DOMAIN, "abcdef-123456")}) diagnostics = await get_diagnostics_for_device( hass, hass_client, init_integration, device diff --git a/tests/components/goalzero/test_init.py b/tests/components/goalzero/test_init.py index 2603f0bf93a52d..287af75c9cd8fb 100644 --- a/tests/components/goalzero/test_init.py +++ b/tests/components/goalzero/test_init.py @@ -72,7 +72,7 @@ async def test_device_info( entry = await async_init_integration(hass, aioclient_mock) device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, entry.entry_id)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, entry.entry_id)}) assert device.connections == {("mac", "12:34:56:78:90:12")} assert device.identifiers == {(DOMAIN, entry.entry_id)} diff --git a/tests/components/gogogate2/test_cover.py b/tests/components/gogogate2/test_cover.py index 576cf16044e685..00cc0057d7ca02 100644 --- a/tests/components/gogogate2/test_cover.py +++ b/tests/components/gogogate2/test_cover.py @@ -334,7 +334,7 @@ async def test_device_info_ismartgate( assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() - device = device_registry.async_get_device({(DOMAIN, "xyz")}) + device = device_registry.async_get_device(identifiers={(DOMAIN, "xyz")}) assert device assert device.manufacturer == MANUFACTURER assert device.name == "mycontroller" @@ -369,7 +369,7 @@ async def test_device_info_gogogate2( assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() - device = device_registry.async_get_device({(DOMAIN, "xyz")}) + device = device_registry.async_get_device(identifiers={(DOMAIN, "xyz")}) assert device assert device.manufacturer == MANUFACTURER assert device.name == "mycontroller" diff --git a/tests/components/google_mail/test_init.py b/tests/components/google_mail/test_init.py index 9580430621b589..a069ae0807b1b1 100644 --- a/tests/components/google_mail/test_init.py +++ b/tests/components/google_mail/test_init.py @@ -123,7 +123,7 @@ async def test_device_info( device_registry = dr.async_get(hass) entry = hass.config_entries.async_entries(DOMAIN)[0] - device = device_registry.async_get_device({(DOMAIN, entry.entry_id)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, entry.entry_id)}) assert device.entry_type is dr.DeviceEntryType.SERVICE assert device.identifiers == {(DOMAIN, entry.entry_id)} diff --git a/tests/components/heos/test_media_player.py b/tests/components/heos/test_media_player.py index c429c8b46a80ed..1784ba83446183 100644 --- a/tests/components/heos/test_media_player.py +++ b/tests/components/heos/test_media_player.py @@ -263,7 +263,7 @@ async def test_updates_from_players_changed_new_ids( event = asyncio.Event() # Assert device registry matches current id - assert device_registry.async_get_device({(DOMAIN, 1)}) + assert device_registry.async_get_device(identifiers={(DOMAIN, 1)}) # Assert entity registry matches current id assert ( entity_registry.async_get_entity_id(MEDIA_PLAYER_DOMAIN, DOMAIN, "1") @@ -284,7 +284,7 @@ async def set_signal(): # Assert device registry identifiers were updated assert len(device_registry.devices) == 2 - assert device_registry.async_get_device({(DOMAIN, 101)}) + assert device_registry.async_get_device(identifiers={(DOMAIN, 101)}) # Assert entity registry unique id was updated assert len(entity_registry.entities) == 2 assert ( diff --git a/tests/components/home_plus_control/test_switch.py b/tests/components/home_plus_control/test_switch.py index 9c7736e2b8eb32..ead1f83cb94ed6 100644 --- a/tests/components/home_plus_control/test_switch.py +++ b/tests/components/home_plus_control/test_switch.py @@ -55,7 +55,7 @@ def one_entity_state(hass, device_uid): entity_reg = er.async_get(hass) device_reg = dr.async_get(hass) - device_id = device_reg.async_get_device({(DOMAIN, device_uid)}).id + device_id = device_reg.async_get_device(identifiers={(DOMAIN, device_uid)}).id entity_entries = er.async_entries_for_device(entity_reg, device_id) assert len(entity_entries) == 1 diff --git a/tests/components/homekit/test_homekit.py b/tests/components/homekit/test_homekit.py index 112c138a8438a4..109f4205901afa 100644 --- a/tests/components/homekit/test_homekit.py +++ b/tests/components/homekit/test_homekit.py @@ -744,7 +744,7 @@ async def test_homekit_start( assert device_registry.async_get(bridge_with_wrong_mac.id) is None device = device_registry.async_get_device( - {(DOMAIN, entry.entry_id, BRIDGE_SERIAL_NUMBER)} + identifiers={(DOMAIN, entry.entry_id, BRIDGE_SERIAL_NUMBER)} ) assert device formatted_mac = dr.format_mac(homekit.driver.state.mac) @@ -760,7 +760,7 @@ async def test_homekit_start( await homekit.async_start() device = device_registry.async_get_device( - {(DOMAIN, entry.entry_id, BRIDGE_SERIAL_NUMBER)} + identifiers={(DOMAIN, entry.entry_id, BRIDGE_SERIAL_NUMBER)} ) assert device formatted_mac = dr.format_mac(homekit.driver.state.mac) @@ -953,7 +953,7 @@ async def test_homekit_unpair( formatted_mac = dr.format_mac(state.mac) hk_bridge_dev = device_registry.async_get_device( - {}, {(dr.CONNECTION_NETWORK_MAC, formatted_mac)} + connections={(dr.CONNECTION_NETWORK_MAC, formatted_mac)} ) await hass.services.async_call( diff --git a/tests/components/homekit_controller/common.py b/tests/components/homekit_controller/common.py index 19e1b738aedf67..0c27e0a3648eaf 100644 --- a/tests/components/homekit_controller/common.py +++ b/tests/components/homekit_controller/common.py @@ -325,9 +325,7 @@ async def _do_assertions(expected: DeviceTestInfo) -> dr.DeviceEntry: # we have detected broken serial numbers (and serial number is not used as an identifier). device = device_registry.async_get_device( - { - (IDENTIFIER_ACCESSORY_ID, expected.unique_id), - } + identifiers={(IDENTIFIER_ACCESSORY_ID, expected.unique_id)} ) logger.debug("Comparing device %r to %r", device, expected) diff --git a/tests/components/hue/test_device_trigger_v1.py b/tests/components/hue/test_device_trigger_v1.py index aea91c06e88d2c..3be150f02697a1 100644 --- a/tests/components/hue/test_device_trigger_v1.py +++ b/tests/components/hue/test_device_trigger_v1.py @@ -29,7 +29,7 @@ async def test_get_triggers( # Get triggers for specific tap switch hue_tap_device = device_reg.async_get_device( - {(hue.DOMAIN, "00:00:00:00:00:44:23:08")} + identifiers={(hue.DOMAIN, "00:00:00:00:00:44:23:08")} ) triggers = await async_get_device_automations( hass, DeviceAutomationType.TRIGGER, hue_tap_device.id @@ -50,7 +50,7 @@ async def test_get_triggers( # Get triggers for specific dimmer switch hue_dimmer_device = device_reg.async_get_device( - {(hue.DOMAIN, "00:17:88:01:10:3e:3a:dc")} + identifiers={(hue.DOMAIN, "00:17:88:01:10:3e:3a:dc")} ) hue_bat_sensor = entity_registry.async_get( "sensor.hue_dimmer_switch_1_battery_level" @@ -95,7 +95,7 @@ async def test_if_fires_on_state_change( # Set an automation with a specific tap switch trigger hue_tap_device = device_reg.async_get_device( - {(hue.DOMAIN, "00:00:00:00:00:44:23:08")} + identifiers={(hue.DOMAIN, "00:00:00:00:00:44:23:08")} ) assert await async_setup_component( hass, diff --git a/tests/components/hue/test_device_trigger_v2.py b/tests/components/hue/test_device_trigger_v2.py index 26c323617d294c..ab400c53ee4278 100644 --- a/tests/components/hue/test_device_trigger_v2.py +++ b/tests/components/hue/test_device_trigger_v2.py @@ -60,7 +60,7 @@ async def test_get_triggers( # Get triggers for `Wall switch with 2 controls` hue_wall_switch_device = device_reg.async_get_device( - {(hue.DOMAIN, "3ff06175-29e8-44a8-8fe7-af591b0025da")} + identifiers={(hue.DOMAIN, "3ff06175-29e8-44a8-8fe7-af591b0025da")} ) hue_bat_sensor = entity_registry.async_get( "sensor.wall_switch_with_2_controls_battery" diff --git a/tests/components/hue/test_sensor_v1.py b/tests/components/hue/test_sensor_v1.py index f7f0818803663f..d5ac8406f24e30 100644 --- a/tests/components/hue/test_sensor_v1.py +++ b/tests/components/hue/test_sensor_v1.py @@ -460,7 +460,7 @@ async def test_hue_events(hass: HomeAssistant, mock_bridge_v1, device_reg) -> No assert len(events) == 0 hue_tap_device = device_reg.async_get_device( - {(hue.DOMAIN, "00:00:00:00:00:44:23:08")} + identifiers={(hue.DOMAIN, "00:00:00:00:00:44:23:08")} ) mock_bridge_v1.api.sensors["7"].last_event = {"type": "button"} @@ -492,7 +492,7 @@ async def test_hue_events(hass: HomeAssistant, mock_bridge_v1, device_reg) -> No } hue_dimmer_device = device_reg.async_get_device( - {(hue.DOMAIN, "00:17:88:01:10:3e:3a:dc")} + identifiers={(hue.DOMAIN, "00:17:88:01:10:3e:3a:dc")} ) new_sensor_response = dict(new_sensor_response) @@ -595,7 +595,7 @@ async def test_hue_events(hass: HomeAssistant, mock_bridge_v1, device_reg) -> No await hass.async_block_till_done() hue_aurora_device = device_reg.async_get_device( - {(hue.DOMAIN, "ff:ff:00:0f:e7:fd:bc:b7")} + identifiers={(hue.DOMAIN, "ff:ff:00:0f:e7:fd:bc:b7")} ) assert len(mock_bridge_v1.mock_requests) == 6 diff --git a/tests/components/hyperion/test_camera.py b/tests/components/hyperion/test_camera.py index f83ed9c7e78ee1..a6234f34593c9c 100644 --- a/tests/components/hyperion/test_camera.py +++ b/tests/components/hyperion/test_camera.py @@ -192,7 +192,7 @@ async def test_device_info(hass: HomeAssistant) -> None: device_id = get_hyperion_device_id(TEST_SYSINFO_ID, TEST_INSTANCE) device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, device_id)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, device_id)}) assert device assert device.config_entries == {TEST_CONFIG_ENTRY_ID} assert device.identifiers == {(DOMAIN, device_id)} diff --git a/tests/components/hyperion/test_light.py b/tests/components/hyperion/test_light.py index 667c73a20ac65c..6c4cc4e512e4cd 100644 --- a/tests/components/hyperion/test_light.py +++ b/tests/components/hyperion/test_light.py @@ -775,7 +775,7 @@ async def test_device_info(hass: HomeAssistant) -> None: device_id = get_hyperion_device_id(TEST_SYSINFO_ID, TEST_INSTANCE) device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, device_id)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, device_id)}) assert device assert device.config_entries == {TEST_CONFIG_ENTRY_ID} assert device.identifiers == {(DOMAIN, device_id)} diff --git a/tests/components/hyperion/test_switch.py b/tests/components/hyperion/test_switch.py index 49338c72c5d023..dcdd86f0902730 100644 --- a/tests/components/hyperion/test_switch.py +++ b/tests/components/hyperion/test_switch.py @@ -164,7 +164,7 @@ async def test_device_info(hass: HomeAssistant) -> None: device_identifer = get_hyperion_device_id(TEST_SYSINFO_ID, TEST_INSTANCE) device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, device_identifer)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, device_identifer)}) assert device assert device.config_entries == {TEST_CONFIG_ENTRY_ID} assert device.identifiers == {(DOMAIN, device_identifer)} diff --git a/tests/components/ibeacon/test_init.py b/tests/components/ibeacon/test_init.py index 2437c7c1351dee..2e3aafb4984ce6 100644 --- a/tests/components/ibeacon/test_init.py +++ b/tests/components/ibeacon/test_init.py @@ -49,13 +49,12 @@ async def test_device_remove_devices( device_registry = dr.async_get(hass) device_entry = device_registry.async_get_device( - { + identifiers={ ( DOMAIN, "426c7565-4368-6172-6d42-6561636f6e73_3838_4949_61DE521B-F0BF-9F44-64D4-75BBE1738105", ) }, - {}, ) assert ( await remove_device(await hass_ws_client(hass), device_entry.id, entry.entry_id) diff --git a/tests/components/lcn/conftest.py b/tests/components/lcn/conftest.py index cf52263e69d6b8..a6bcdf639509d4 100644 --- a/tests/components/lcn/conftest.py +++ b/tests/components/lcn/conftest.py @@ -128,6 +128,6 @@ def get_device(hass, entry, address): """Get LCN device for specified address.""" device_registry = dr.async_get(hass) identifiers = {(DOMAIN, generate_unique_id(entry.entry_id, address))} - device = device_registry.async_get_device(identifiers) + device = device_registry.async_get_device(identifiers=identifiers) assert device return device diff --git a/tests/components/lcn/test_device_trigger.py b/tests/components/lcn/test_device_trigger.py index 637aeec1b0b1e6..47287fbd1d2b90 100644 --- a/tests/components/lcn/test_device_trigger.py +++ b/tests/components/lcn/test_device_trigger.py @@ -55,10 +55,12 @@ async def test_get_triggers_non_module_device( not_included_types = ("transmitter", "transponder", "fingerprint", "send_keys") device_registry = dr.async_get(hass) - host_device = device_registry.async_get_device({(DOMAIN, entry.entry_id)}) + host_device = device_registry.async_get_device( + identifiers={(DOMAIN, entry.entry_id)} + ) group_device = get_device(hass, entry, (0, 5, True)) resource_device = device_registry.async_get_device( - {(DOMAIN, f"{entry.entry_id}-m000007-output1")} + identifiers={(DOMAIN, f"{entry.entry_id}-m000007-output1")} ) for device in (host_device, group_device, resource_device): diff --git a/tests/components/lidarr/test_init.py b/tests/components/lidarr/test_init.py index 2a217bebd5f8dc..5d6961e57c3bf2 100644 --- a/tests/components/lidarr/test_init.py +++ b/tests/components/lidarr/test_init.py @@ -52,7 +52,7 @@ async def test_device_info( entry = hass.config_entries.async_entries(DOMAIN)[0] device_registry = dr.async_get(hass) await hass.async_block_till_done() - device = device_registry.async_get_device({(DOMAIN, entry.entry_id)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, entry.entry_id)}) assert device.configuration_url == "http://127.0.0.1:8668" assert device.identifiers == {(DOMAIN, entry.entry_id)} diff --git a/tests/components/lifx/test_light.py b/tests/components/lifx/test_light.py index f64af98c9b5c0b..70a5a89a3ae113 100644 --- a/tests/components/lifx/test_light.py +++ b/tests/components/lifx/test_light.py @@ -100,7 +100,7 @@ async def test_light_unique_id(hass: HomeAssistant) -> None: device_registry = dr.async_get(hass) device = device_registry.async_get_device( - identifiers=set(), connections={(dr.CONNECTION_NETWORK_MAC, SERIAL)} + connections={(dr.CONNECTION_NETWORK_MAC, SERIAL)} ) assert device.identifiers == {(DOMAIN, SERIAL)} @@ -123,7 +123,6 @@ async def test_light_unique_id_new_firmware(hass: HomeAssistant) -> None: assert entity_registry.async_get(entity_id).unique_id == SERIAL device_registry = dr.async_get(hass) device = device_registry.async_get_device( - identifiers=set(), connections={(dr.CONNECTION_NETWORK_MAC, MAC_ADDRESS)}, ) assert device.identifiers == {(DOMAIN, SERIAL)} diff --git a/tests/components/matter/test_adapter.py b/tests/components/matter/test_adapter.py index 62ed847bf28f8b..8ed309f61df468 100644 --- a/tests/components/matter/test_adapter.py +++ b/tests/components/matter/test_adapter.py @@ -41,7 +41,9 @@ async def test_device_registry_single_node_device( dev_reg = dr.async_get(hass) entry = dev_reg.async_get_device( - {(DOMAIN, "deviceid_00000000000004D2-0000000000000001-MatterNodeDevice")} + identifiers={ + (DOMAIN, "deviceid_00000000000004D2-0000000000000001-MatterNodeDevice") + } ) assert entry is not None @@ -70,7 +72,9 @@ async def test_device_registry_single_node_device_alt( dev_reg = dr.async_get(hass) entry = dev_reg.async_get_device( - {(DOMAIN, "deviceid_00000000000004D2-0000000000000001-MatterNodeDevice")} + identifiers={ + (DOMAIN, "deviceid_00000000000004D2-0000000000000001-MatterNodeDevice") + } ) assert entry is not None @@ -96,7 +100,7 @@ async def test_device_registry_bridge( dev_reg = dr.async_get(hass) # Validate bridge - bridge_entry = dev_reg.async_get_device({(DOMAIN, "mock-hub-id")}) + bridge_entry = dev_reg.async_get_device(identifiers={(DOMAIN, "mock-hub-id")}) assert bridge_entry is not None assert bridge_entry.name == "My Mock Bridge" @@ -106,7 +110,9 @@ async def test_device_registry_bridge( assert bridge_entry.sw_version == "123.4.5" # Device 1 - device1_entry = dev_reg.async_get_device({(DOMAIN, "mock-id-kitchen-ceiling")}) + device1_entry = dev_reg.async_get_device( + identifiers={(DOMAIN, "mock-id-kitchen-ceiling")} + ) assert device1_entry is not None assert device1_entry.via_device_id == bridge_entry.id @@ -117,7 +123,9 @@ async def test_device_registry_bridge( assert device1_entry.sw_version == "67.8.9" # Device 2 - device2_entry = dev_reg.async_get_device({(DOMAIN, "mock-id-living-room-ceiling")}) + device2_entry = dev_reg.async_get_device( + identifiers={(DOMAIN, "mock-id-living-room-ceiling")} + ) assert device2_entry is not None assert device2_entry.via_device_id == bridge_entry.id diff --git a/tests/components/mobile_app/test_webhook.py b/tests/components/mobile_app/test_webhook.py index ce1dc19319aa78..4faf48e2118a62 100644 --- a/tests/components/mobile_app/test_webhook.py +++ b/tests/components/mobile_app/test_webhook.py @@ -857,7 +857,9 @@ async def test_webhook_handle_scan_tag( hass: HomeAssistant, create_registrations, webhook_client ) -> None: """Test that we can scan tags.""" - device = dr.async_get(hass).async_get_device({(DOMAIN, "mock-device-id")}) + device = dr.async_get(hass).async_get_device( + identifiers={(DOMAIN, "mock-device-id")} + ) assert device is not None events = async_capture_events(hass, EVENT_TAG_SCANNED) diff --git a/tests/components/motioneye/test_camera.py b/tests/components/motioneye/test_camera.py index 6972bee35d019b..5f5c5f7854eb13 100644 --- a/tests/components/motioneye/test_camera.py +++ b/tests/components/motioneye/test_camera.py @@ -159,15 +159,17 @@ async def test_setup_camera_new_data_camera_removed(hass: HomeAssistant) -> None await hass.async_block_till_done() assert hass.states.get(TEST_CAMERA_ENTITY_ID) - assert device_registry.async_get_device({TEST_CAMERA_DEVICE_IDENTIFIER}) + assert device_registry.async_get_device(identifiers={TEST_CAMERA_DEVICE_IDENTIFIER}) client.async_get_cameras = AsyncMock(return_value={KEY_CAMERAS: []}) async_fire_time_changed(hass, dt_util.utcnow() + DEFAULT_SCAN_INTERVAL) await hass.async_block_till_done() await hass.async_block_till_done() assert not hass.states.get(TEST_CAMERA_ENTITY_ID) - assert not device_registry.async_get_device({TEST_CAMERA_DEVICE_IDENTIFIER}) - assert not device_registry.async_get_device({(DOMAIN, old_device_id)}) + assert not device_registry.async_get_device( + identifiers={TEST_CAMERA_DEVICE_IDENTIFIER} + ) + assert not device_registry.async_get_device(identifiers={(DOMAIN, old_device_id)}) assert not entity_registry.async_get_entity_id( DOMAIN, "camera", old_entity_unique_id ) @@ -320,7 +322,7 @@ async def test_device_info(hass: HomeAssistant) -> None: device_identifier = get_motioneye_device_identifier(entry.entry_id, TEST_CAMERA_ID) device_registry = dr.async_get(hass) - device = device_registry.async_get_device({device_identifier}) + device = device_registry.async_get_device(identifiers={device_identifier}) assert device assert device.config_entries == {TEST_CONFIG_ENTRY_ID} assert device.identifiers == {device_identifier} diff --git a/tests/components/motioneye/test_sensor.py b/tests/components/motioneye/test_sensor.py index ea07834976b2b9..5494e69d9e9152 100644 --- a/tests/components/motioneye/test_sensor.py +++ b/tests/components/motioneye/test_sensor.py @@ -88,7 +88,7 @@ async def test_sensor_device_info(hass: HomeAssistant) -> None: ) device_registry = dr.async_get(hass) - device = device_registry.async_get_device({device_identifer}) + device = device_registry.async_get_device(identifiers={device_identifer}) assert device entity_registry = er.async_get(hass) diff --git a/tests/components/motioneye/test_switch.py b/tests/components/motioneye/test_switch.py index 03c39a4b5424e7..f0fe4f1faba95a 100644 --- a/tests/components/motioneye/test_switch.py +++ b/tests/components/motioneye/test_switch.py @@ -193,7 +193,7 @@ async def test_switch_device_info(hass: HomeAssistant) -> None: ) device_registry = dr.async_get(hass) - device = device_registry.async_get_device({device_identifer}) + device = device_registry.async_get_device(identifiers={device_identifer}) assert device entity_registry = er.async_get(hass) diff --git a/tests/components/mqtt/test_common.py b/tests/components/mqtt/test_common.py index cd1cc7280c60ac..cfd714725c43e8 100644 --- a/tests/components/mqtt/test_common.py +++ b/tests/components/mqtt/test_common.py @@ -1001,7 +1001,7 @@ async def help_test_entity_device_info_with_identifier( async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None assert device.identifiers == {("mqtt", "helloworld")} assert device.manufacturer == "Whatever" @@ -1036,7 +1036,7 @@ async def help_test_entity_device_info_with_connection( await hass.async_block_till_done() device = registry.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, "02:5b:26:a8:dc:12")} + connections={(dr.CONNECTION_NETWORK_MAC, "02:5b:26:a8:dc:12")} ) assert device is not None assert device.connections == {(dr.CONNECTION_NETWORK_MAC, "02:5b:26:a8:dc:12")} @@ -1069,14 +1069,14 @@ async def help_test_entity_device_info_remove( async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data) await hass.async_block_till_done() - device = dev_registry.async_get_device({("mqtt", "helloworld")}) + device = dev_registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None assert ent_registry.async_get_entity_id(domain, mqtt.DOMAIN, "veryunique") async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", "") await hass.async_block_till_done() - device = dev_registry.async_get_device({("mqtt", "helloworld")}) + device = dev_registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is None assert not ent_registry.async_get_entity_id(domain, mqtt.DOMAIN, "veryunique") @@ -1103,7 +1103,7 @@ async def help_test_entity_device_info_update( async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None assert device.name == "Beer" @@ -1112,7 +1112,7 @@ async def help_test_entity_device_info_update( async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None assert device.name == "Milk" @@ -1232,7 +1232,7 @@ async def help_test_entity_debug_info( async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None debug_info_data = debug_info.info_for_device(hass, device.id) @@ -1272,7 +1272,7 @@ async def help_test_entity_debug_info_max_messages( async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None debug_info_data = debug_info.info_for_device(hass, device.id) @@ -1352,7 +1352,7 @@ async def help_test_entity_debug_info_message( async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None debug_info_data = debug_info.info_for_device(hass, device.id) @@ -1443,7 +1443,7 @@ async def help_test_entity_debug_info_remove( async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None debug_info_data = debug_info.info_for_device(hass, device.id) @@ -1493,7 +1493,7 @@ async def help_test_entity_debug_info_update_entity_id( async_fire_mqtt_message(hass, f"homeassistant/{domain}/bla/config", data) await hass.async_block_till_done() - device = device_registry.async_get_device({("mqtt", "helloworld")}) + device = device_registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None debug_info_data = debug_info.info_for_device(hass, device.id) @@ -1555,7 +1555,7 @@ async def help_test_entity_disabled_by_default( await hass.async_block_till_done() entity_id = ent_registry.async_get_entity_id(domain, mqtt.DOMAIN, "veryunique1") assert entity_id is not None and hass.states.get(entity_id) is None - assert dev_registry.async_get_device({("mqtt", "helloworld")}) + assert dev_registry.async_get_device(identifiers={("mqtt", "helloworld")}) # Discover an enabled entity, tied to the same device config["enabled_by_default"] = True @@ -1571,7 +1571,7 @@ async def help_test_entity_disabled_by_default( await hass.async_block_till_done() assert not ent_registry.async_get_entity_id(domain, mqtt.DOMAIN, "veryunique1") assert not ent_registry.async_get_entity_id(domain, mqtt.DOMAIN, "veryunique2") - assert not dev_registry.async_get_device({("mqtt", "helloworld")}) + assert not dev_registry.async_get_device(identifiers={("mqtt", "helloworld")}) async def help_test_entity_category( diff --git a/tests/components/mqtt/test_device_tracker.py b/tests/components/mqtt/test_device_tracker.py index 3793902258d618..ddce53bfca0c90 100644 --- a/tests/components/mqtt/test_device_tracker.py +++ b/tests/components/mqtt/test_device_tracker.py @@ -249,7 +249,7 @@ async def test_cleanup_device_tracker( await hass.async_block_till_done() # Verify device and registry entries are created - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert device_entry is not None entity_entry = entity_registry.async_get("device_tracker.mqtt_unique") assert entity_entry is not None @@ -273,7 +273,7 @@ async def test_cleanup_device_tracker( await hass.async_block_till_done() # Verify device and registry entries are cleared - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert device_entry is None entity_entry = entity_registry.async_get("device_tracker.mqtt_unique") assert entity_entry is None diff --git a/tests/components/mqtt/test_device_trigger.py b/tests/components/mqtt/test_device_trigger.py index 9f3b7565332c41..485c2774f7b4d9 100644 --- a/tests/components/mqtt/test_device_trigger.py +++ b/tests/components/mqtt/test_device_trigger.py @@ -64,7 +64,7 @@ async def test_get_triggers( async_fire_mqtt_message(hass, "homeassistant/device_automation/bla/config", data1) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) expected_triggers = [ { "platform": "device", @@ -98,7 +98,7 @@ async def test_get_unknown_triggers( async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data1) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert await async_setup_component( hass, @@ -145,7 +145,7 @@ async def test_get_non_existing_triggers( async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data1) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) triggers = await async_get_device_automations( hass, DeviceAutomationType.TRIGGER, device_entry.id ) @@ -171,7 +171,7 @@ async def test_discover_bad_triggers( ) async_fire_mqtt_message(hass, "homeassistant/device_automation/bla/config", data0) await hass.async_block_till_done() - assert device_registry.async_get_device({("mqtt", "0AFFD2")}) is None + assert device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) is None # Test sending correct data data1 = ( @@ -185,7 +185,7 @@ async def test_discover_bad_triggers( async_fire_mqtt_message(hass, "homeassistant/device_automation/bla/config", data1) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) expected_triggers = [ { "platform": "device", @@ -235,7 +235,7 @@ async def test_update_remove_triggers( async_fire_mqtt_message(hass, "homeassistant/device_automation/bla/config", data1) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) expected_triggers1 = [ { "platform": "device", @@ -268,7 +268,7 @@ async def test_update_remove_triggers( async_fire_mqtt_message(hass, "homeassistant/device_automation/bla/config", "") await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert device_entry is None @@ -299,7 +299,7 @@ async def test_if_fires_on_mqtt_message( async_fire_mqtt_message(hass, "homeassistant/device_automation/bla1/config", data1) async_fire_mqtt_message(hass, "homeassistant/device_automation/bla2/config", data2) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert await async_setup_component( hass, @@ -380,7 +380,7 @@ async def test_if_fires_on_mqtt_message_template( async_fire_mqtt_message(hass, "homeassistant/device_automation/bla1/config", data1) async_fire_mqtt_message(hass, "homeassistant/device_automation/bla2/config", data2) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert await async_setup_component( hass, @@ -463,7 +463,7 @@ async def test_if_fires_on_mqtt_message_late_discover( ) async_fire_mqtt_message(hass, "homeassistant/sensor/bla0/config", data0) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert await async_setup_component( hass, @@ -543,7 +543,7 @@ async def test_if_fires_on_mqtt_message_after_update( ) async_fire_mqtt_message(hass, "homeassistant/device_automation/bla1/config", data1) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert await async_setup_component( hass, @@ -615,7 +615,7 @@ async def test_no_resubscribe_same_topic( ) async_fire_mqtt_message(hass, "homeassistant/device_automation/bla1/config", data1) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert await async_setup_component( hass, @@ -663,7 +663,7 @@ async def test_not_fires_on_mqtt_message_after_remove_by_mqtt( ) async_fire_mqtt_message(hass, "homeassistant/device_automation/bla1/config", data1) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert await async_setup_component( hass, @@ -735,7 +735,7 @@ async def test_not_fires_on_mqtt_message_after_remove_from_registry( ) async_fire_mqtt_message(hass, "homeassistant/device_automation/bla1/config", data1) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert await async_setup_component( hass, @@ -801,7 +801,7 @@ async def test_attach_remove( ) async_fire_mqtt_message(hass, "homeassistant/device_automation/bla1/config", data1) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) calls = [] @@ -864,7 +864,7 @@ async def test_attach_remove_late( ) async_fire_mqtt_message(hass, "homeassistant/sensor/bla0/config", data0) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) calls = [] @@ -930,7 +930,7 @@ async def test_attach_remove_late2( ) async_fire_mqtt_message(hass, "homeassistant/sensor/bla0/config", data0) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) calls = [] @@ -999,7 +999,7 @@ async def test_entity_device_info_with_connection( await hass.async_block_till_done() device = registry.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, "02:5b:26:a8:dc:12")} + connections={(dr.CONNECTION_NETWORK_MAC, "02:5b:26:a8:dc:12")} ) assert device is not None assert device.connections == {(dr.CONNECTION_NETWORK_MAC, "02:5b:26:a8:dc:12")} @@ -1036,7 +1036,7 @@ async def test_entity_device_info_with_identifier( async_fire_mqtt_message(hass, "homeassistant/device_automation/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None assert device.identifiers == {("mqtt", "helloworld")} assert device.manufacturer == "Whatever" @@ -1072,7 +1072,7 @@ async def test_entity_device_info_update( async_fire_mqtt_message(hass, "homeassistant/device_automation/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None assert device.name == "Beer" @@ -1081,7 +1081,7 @@ async def test_entity_device_info_update( async_fire_mqtt_message(hass, "homeassistant/device_automation/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None assert device.name == "Milk" @@ -1110,7 +1110,9 @@ async def test_cleanup_trigger( await hass.async_block_till_done() # Verify device registry entry is created - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is not None triggers = await async_get_device_automations( @@ -1134,7 +1136,9 @@ async def test_cleanup_trigger( await hass.async_block_till_done() # Verify device registry entry is cleared - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is None # Verify retained discovery topic has been cleared @@ -1163,7 +1167,9 @@ async def test_cleanup_device( await hass.async_block_till_done() # Verify device registry entry is created - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is not None triggers = await async_get_device_automations( @@ -1175,7 +1181,9 @@ async def test_cleanup_device( await hass.async_block_till_done() # Verify device registry entry is cleared - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is None @@ -1210,7 +1218,9 @@ async def test_cleanup_device_several_triggers( await hass.async_block_till_done() # Verify device registry entry is created - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is not None triggers = await async_get_device_automations( @@ -1224,7 +1234,9 @@ async def test_cleanup_device_several_triggers( await hass.async_block_till_done() # Verify device registry entry is not cleared - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is not None triggers = await async_get_device_automations( @@ -1237,7 +1249,9 @@ async def test_cleanup_device_several_triggers( await hass.async_block_till_done() # Verify device registry entry is cleared - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is None @@ -1274,7 +1288,9 @@ async def test_cleanup_device_with_entity1( await hass.async_block_till_done() # Verify device registry entry is created - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is not None triggers = await async_get_device_automations( @@ -1286,7 +1302,9 @@ async def test_cleanup_device_with_entity1( await hass.async_block_till_done() # Verify device registry entry is not cleared - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is not None triggers = await async_get_device_automations( @@ -1298,7 +1316,9 @@ async def test_cleanup_device_with_entity1( await hass.async_block_till_done() # Verify device registry entry is cleared - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is None @@ -1335,7 +1355,9 @@ async def test_cleanup_device_with_entity2( await hass.async_block_till_done() # Verify device registry entry is created - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is not None triggers = await async_get_device_automations( @@ -1347,7 +1369,9 @@ async def test_cleanup_device_with_entity2( await hass.async_block_till_done() # Verify device registry entry is not cleared - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is not None triggers = await async_get_device_automations( @@ -1359,7 +1383,9 @@ async def test_cleanup_device_with_entity2( await hass.async_block_till_done() # Verify device registry entry is cleared - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is None @@ -1404,7 +1430,7 @@ async def test_trigger_debug_info( await hass.async_block_till_done() device = registry.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, "02:5b:26:a8:dc:12")} + connections={(dr.CONNECTION_NETWORK_MAC, "02:5b:26:a8:dc:12")} ) assert device is not None @@ -1457,7 +1483,7 @@ async def test_unload_entry( ) async_fire_mqtt_message(hass, "homeassistant/device_automation/bla1/config", data1) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert await async_setup_component( hass, diff --git a/tests/components/mqtt/test_diagnostics.py b/tests/components/mqtt/test_diagnostics.py index 81a86f1c61f9f9..fb1033848743ca 100644 --- a/tests/components/mqtt/test_diagnostics.py +++ b/tests/components/mqtt/test_diagnostics.py @@ -75,7 +75,7 @@ async def test_entry_diagnostics( ) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) expected_debug_info = { "entities": [ @@ -190,7 +190,7 @@ async def test_redact_diagnostics( async_fire_mqtt_message(hass, "attributes-topic", location_data) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) expected_debug_info = { "entities": [ diff --git a/tests/components/mqtt/test_discovery.py b/tests/components/mqtt/test_discovery.py index 14074ce113546a..62b87bdb791c04 100644 --- a/tests/components/mqtt/test_discovery.py +++ b/tests/components/mqtt/test_discovery.py @@ -727,7 +727,7 @@ async def test_cleanup_device( await hass.async_block_till_done() # Verify device and registry entries are created - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert device_entry is not None entity_entry = entity_registry.async_get("sensor.mqtt_sensor") assert entity_entry is not None @@ -751,7 +751,7 @@ async def test_cleanup_device( await hass.async_block_till_done() # Verify device and registry entries are cleared - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert device_entry is None entity_entry = entity_registry.async_get("sensor.mqtt_sensor") assert entity_entry is None @@ -786,7 +786,7 @@ async def test_cleanup_device_mqtt( await hass.async_block_till_done() # Verify device and registry entries are created - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert device_entry is not None entity_entry = entity_registry.async_get("sensor.mqtt_sensor") assert entity_entry is not None @@ -799,7 +799,7 @@ async def test_cleanup_device_mqtt( await hass.async_block_till_done() # Verify device and registry entries are cleared - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert device_entry is None entity_entry = entity_registry.async_get("sensor.mqtt_sensor") assert entity_entry is None @@ -866,7 +866,7 @@ async def test_cleanup_device_multiple_config_entries( # Verify device and registry entries are created device_entry = device_registry.async_get_device( - set(), {("mac", "12:34:56:AB:CD:EF")} + connections={("mac", "12:34:56:AB:CD:EF")} ) assert device_entry is not None assert device_entry.config_entries == { @@ -897,7 +897,7 @@ async def test_cleanup_device_multiple_config_entries( # Verify device is still there but entity is cleared device_entry = device_registry.async_get_device( - set(), {("mac", "12:34:56:AB:CD:EF")} + connections={("mac", "12:34:56:AB:CD:EF")} ) assert device_entry is not None entity_entry = entity_registry.async_get("sensor.mqtt_sensor") @@ -966,7 +966,7 @@ async def test_cleanup_device_multiple_config_entries_mqtt( # Verify device and registry entries are created device_entry = device_registry.async_get_device( - set(), {("mac", "12:34:56:AB:CD:EF")} + connections={("mac", "12:34:56:AB:CD:EF")} ) assert device_entry is not None assert device_entry.config_entries == { @@ -989,7 +989,7 @@ async def test_cleanup_device_multiple_config_entries_mqtt( # Verify device is still there but entity is cleared device_entry = device_registry.async_get_device( - set(), {("mac", "12:34:56:AB:CD:EF")} + connections={("mac", "12:34:56:AB:CD:EF")} ) assert device_entry is not None entity_entry = entity_registry.async_get("sensor.mqtt_sensor") @@ -1518,7 +1518,7 @@ async def test_clear_config_topic_disabled_entity( # Verify device is created device_entry = device_registry.async_get_device( - set(), {("mac", "12:34:56:AB:CD:EF")} + connections={("mac", "12:34:56:AB:CD:EF")} ) assert device_entry is not None @@ -1584,7 +1584,7 @@ async def test_clean_up_registry_monitoring( # Verify device is created device_entry = device_registry.async_get_device( - set(), {("mac", "12:34:56:AB:CD:EF")} + connections={("mac", "12:34:56:AB:CD:EF")} ) assert device_entry is not None diff --git a/tests/components/mqtt/test_init.py b/tests/components/mqtt/test_init.py index 08aa53aec7a1b5..9432f23130161a 100644 --- a/tests/components/mqtt/test_init.py +++ b/tests/components/mqtt/test_init.py @@ -2604,7 +2604,7 @@ async def test_default_entry_setting_are_applied( async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert device_entry is not None @@ -2757,7 +2757,7 @@ async def test_mqtt_ws_remove_discovered_device( await hass.async_block_till_done() # Verify device entry is created - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert device_entry is not None client = await hass_ws_client(hass) @@ -2774,7 +2774,7 @@ async def test_mqtt_ws_remove_discovered_device( assert response["success"] # Verify device entry is cleared - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert device_entry is None @@ -2809,7 +2809,7 @@ async def test_mqtt_ws_get_device_debug_info( await hass.async_block_till_done() # Verify device entry is created - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert device_entry is not None client = await hass_ws_client(hass) @@ -2864,7 +2864,7 @@ async def test_mqtt_ws_get_device_debug_info_binary( await hass.async_block_till_done() # Verify device entry is created - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) assert device_entry is not None small_png = ( @@ -2971,7 +2971,7 @@ async def test_debug_info_multiple_devices( for dev in devices: domain = dev["domain"] id = dev["config"]["device"]["identifiers"][0] - device = registry.async_get_device({("mqtt", id)}) + device = registry.async_get_device(identifiers={("mqtt", id)}) assert device is not None debug_info_data = debug_info.info_for_device(hass, device.id) @@ -3052,7 +3052,7 @@ async def test_debug_info_multiple_entities_triggers( await hass.async_block_till_done() device_id = config[0]["config"]["device"]["identifiers"][0] - device = registry.async_get_device({("mqtt", device_id)}) + device = registry.async_get_device(identifiers={("mqtt", device_id)}) assert device is not None debug_info_data = debug_info.info_for_device(hass, device.id) assert len(debug_info_data["entities"]) == 2 @@ -3132,7 +3132,7 @@ async def test_debug_info_wildcard( async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None debug_info_data = debug_info.info_for_device(hass, device.id) @@ -3180,7 +3180,7 @@ async def test_debug_info_filter_same( async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None debug_info_data = debug_info.info_for_device(hass, device.id) @@ -3241,7 +3241,7 @@ async def test_debug_info_same_topic( async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None debug_info_data = debug_info.info_for_device(hass, device.id) @@ -3294,7 +3294,7 @@ async def test_debug_info_qos_retain( async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None debug_info_data = debug_info.info_for_device(hass, device.id) diff --git a/tests/components/mqtt/test_sensor.py b/tests/components/mqtt/test_sensor.py index 8f2aa754bacf31..d5483cf3a748eb 100644 --- a/tests/components/mqtt/test_sensor.py +++ b/tests/components/mqtt/test_sensor.py @@ -1142,7 +1142,7 @@ async def test_entity_device_info_with_hub( async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None assert device.via_device_id == hub.id diff --git a/tests/components/mqtt/test_tag.py b/tests/components/mqtt/test_tag.py index c18e24d1a701b5..55eac636edb40b 100644 --- a/tests/components/mqtt/test_tag.py +++ b/tests/components/mqtt/test_tag.py @@ -75,13 +75,13 @@ async def test_discover_bad_tag( data0 = '{ "device":{"identifiers":["0AFFD2"]}, "topics": "foobar/tag_scanned" }' async_fire_mqtt_message(hass, "homeassistant/tag/bla/config", data0) await hass.async_block_till_done() - assert device_registry.async_get_device({("mqtt", "0AFFD2")}) is None + assert device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) is None # Test sending correct data async_fire_mqtt_message(hass, "homeassistant/tag/bla/config", json.dumps(config1)) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) # Fake tag scan. async_fire_mqtt_message(hass, "foobar/tag_scanned", DEFAULT_TAG_SCAN) await hass.async_block_till_done() @@ -100,7 +100,7 @@ async def test_if_fires_on_mqtt_message_with_device( async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", json.dumps(config)) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) # Fake tag scan. async_fire_mqtt_message(hass, "foobar/tag_scanned", DEFAULT_TAG_SCAN) @@ -138,7 +138,7 @@ async def test_if_fires_on_mqtt_message_with_template( async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", json.dumps(config)) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) # Fake tag scan. async_fire_mqtt_message(hass, "foobar/tag_scanned", DEFAULT_TAG_SCAN_JSON) @@ -180,7 +180,7 @@ async def test_if_fires_on_mqtt_message_after_update_with_device( async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", json.dumps(config1)) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) # Fake tag scan. async_fire_mqtt_message(hass, "foobar/tag_scanned", DEFAULT_TAG_SCAN) @@ -275,7 +275,7 @@ async def test_if_fires_on_mqtt_message_after_update_with_template( async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", json.dumps(config1)) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) # Fake tag scan. async_fire_mqtt_message(hass, "foobar/tag_scanned", DEFAULT_TAG_SCAN_JSON) @@ -320,7 +320,7 @@ async def test_no_resubscribe_same_topic( async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", json.dumps(config)) await hass.async_block_till_done() - assert device_registry.async_get_device({("mqtt", "0AFFD2")}) + assert device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) call_count = mqtt_mock.async_subscribe.call_count async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", json.dumps(config)) @@ -340,7 +340,7 @@ async def test_not_fires_on_mqtt_message_after_remove_by_mqtt_with_device( async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", json.dumps(config)) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) # Fake tag scan. async_fire_mqtt_message(hass, "foobar/tag_scanned", DEFAULT_TAG_SCAN) @@ -417,7 +417,7 @@ async def test_not_fires_on_mqtt_message_after_remove_from_registry( async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", json.dumps(config)) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) # Fake tag scan. async_fire_mqtt_message(hass, "foobar/tag_scanned", DEFAULT_TAG_SCAN) @@ -467,7 +467,7 @@ async def test_entity_device_info_with_connection( await hass.async_block_till_done() device = registry.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, "02:5b:26:a8:dc:12")} + connections={(dr.CONNECTION_NETWORK_MAC, "02:5b:26:a8:dc:12")} ) assert device is not None assert device.connections == {(dr.CONNECTION_NETWORK_MAC, "02:5b:26:a8:dc:12")} @@ -501,7 +501,7 @@ async def test_entity_device_info_with_identifier( async_fire_mqtt_message(hass, "homeassistant/tag/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None assert device.identifiers == {("mqtt", "helloworld")} assert device.manufacturer == "Whatever" @@ -534,7 +534,7 @@ async def test_entity_device_info_update( async_fire_mqtt_message(hass, "homeassistant/tag/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None assert device.name == "Beer" @@ -543,7 +543,7 @@ async def test_entity_device_info_update( async_fire_mqtt_message(hass, "homeassistant/tag/bla/config", data) await hass.async_block_till_done() - device = registry.async_get_device({("mqtt", "helloworld")}) + device = registry.async_get_device(identifiers={("mqtt", "helloworld")}) assert device is not None assert device.name == "Milk" @@ -588,20 +588,24 @@ async def test_cleanup_tag( await hass.async_block_till_done() # Verify device registry entries are created - device_entry1 = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry1 = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry1 is not None assert device_entry1.config_entries == {config_entry.entry_id, mqtt_entry.entry_id} - device_entry2 = device_registry.async_get_device({("mqtt", "hejhopp")}) + device_entry2 = device_registry.async_get_device(identifiers={("mqtt", "hejhopp")}) assert device_entry2 is not None # Remove other config entry from the device device_registry.async_update_device( device_entry1.id, remove_config_entry_id=config_entry.entry_id ) - device_entry1 = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry1 = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry1 is not None assert device_entry1.config_entries == {mqtt_entry.entry_id} - device_entry2 = device_registry.async_get_device({("mqtt", "hejhopp")}) + device_entry2 = device_registry.async_get_device(identifiers={("mqtt", "hejhopp")}) assert device_entry2 is not None mqtt_mock.async_publish.assert_not_called() @@ -621,9 +625,11 @@ async def test_cleanup_tag( await hass.async_block_till_done() # Verify device registry entry is cleared - device_entry1 = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry1 = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry1 is None - device_entry2 = device_registry.async_get_device({("mqtt", "hejhopp")}) + device_entry2 = device_registry.async_get_device(identifiers={("mqtt", "hejhopp")}) assert device_entry2 is not None # Verify retained discovery topic has been cleared @@ -649,14 +655,18 @@ async def test_cleanup_device( await hass.async_block_till_done() # Verify device registry entry is created - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is not None async_fire_mqtt_message(hass, "homeassistant/tag/bla/config", "") await hass.async_block_till_done() # Verify device registry entry is cleared - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is None @@ -684,14 +694,18 @@ async def test_cleanup_device_several_tags( await hass.async_block_till_done() # Verify device registry entry is created - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is not None async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", "") await hass.async_block_till_done() # Verify device registry entry is not cleared - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is not None # Fake tag scan. @@ -704,7 +718,9 @@ async def test_cleanup_device_several_tags( await hass.async_block_till_done() # Verify device registry entry is cleared - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is None @@ -749,7 +765,9 @@ async def test_cleanup_device_with_entity_and_trigger_1( await hass.async_block_till_done() # Verify device registry entry is created - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is not None triggers = await async_get_device_automations( @@ -761,7 +779,9 @@ async def test_cleanup_device_with_entity_and_trigger_1( await hass.async_block_till_done() # Verify device registry entry is not cleared - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is not None async_fire_mqtt_message(hass, "homeassistant/device_automation/bla2/config", "") @@ -771,7 +791,9 @@ async def test_cleanup_device_with_entity_and_trigger_1( await hass.async_block_till_done() # Verify device registry entry is cleared - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is None @@ -816,7 +838,9 @@ async def test_cleanup_device_with_entity2( await hass.async_block_till_done() # Verify device registry entry is created - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is not None triggers = await async_get_device_automations( @@ -831,14 +855,18 @@ async def test_cleanup_device_with_entity2( await hass.async_block_till_done() # Verify device registry entry is not cleared - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is not None async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", "") await hass.async_block_till_done() # Verify device registry entry is cleared - device_entry = device_registry.async_get_device({("mqtt", "helloworld")}) + device_entry = device_registry.async_get_device( + identifiers={("mqtt", "helloworld")} + ) assert device_entry is None @@ -899,7 +927,7 @@ async def test_unload_entry( async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", json.dumps(config)) await hass.async_block_till_done() - device_entry = device_registry.async_get_device({("mqtt", "0AFFD2")}) + device_entry = device_registry.async_get_device(identifiers={("mqtt", "0AFFD2")}) # Fake tag scan, should be processed async_fire_mqtt_message(hass, "foobar/tag_scanned", DEFAULT_TAG_SCAN) diff --git a/tests/components/nest/test_device_trigger.py b/tests/components/nest/test_device_trigger.py index f659568c674312..a35b10afa9c456 100644 --- a/tests/components/nest/test_device_trigger.py +++ b/tests/components/nest/test_device_trigger.py @@ -103,7 +103,7 @@ async def test_get_triggers( await setup_platform() device_registry = dr.async_get(hass) - device_entry = device_registry.async_get_device({("nest", DEVICE_ID)}) + device_entry = device_registry.async_get_device(identifiers={("nest", DEVICE_ID)}) expected_triggers = [ { @@ -198,7 +198,7 @@ async def test_triggers_for_invalid_device_id( await setup_platform() device_registry = dr.async_get(hass) - device_entry = device_registry.async_get_device({("nest", DEVICE_ID)}) + device_entry = device_registry.async_get_device(identifiers={("nest", DEVICE_ID)}) assert device_entry is not None # Create an additional device that does not exist. Fetching supported @@ -324,7 +324,7 @@ async def test_subscriber_automation( await setup_platform() device_registry = dr.async_get(hass) - device_entry = device_registry.async_get_device({("nest", DEVICE_ID)}) + device_entry = device_registry.async_get_device(identifiers={("nest", DEVICE_ID)}) assert await setup_automation(hass, device_entry.id, "camera_motion") diff --git a/tests/components/nest/test_diagnostics.py b/tests/components/nest/test_diagnostics.py index 408e4e0d96391d..191253a2a9a0bd 100644 --- a/tests/components/nest/test_diagnostics.py +++ b/tests/components/nest/test_diagnostics.py @@ -117,7 +117,7 @@ async def test_device_diagnostics( assert config_entry.state is ConfigEntryState.LOADED device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, NEST_DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, NEST_DEVICE_ID)}) assert device is not None assert ( diff --git a/tests/components/nest/test_media_source.py b/tests/components/nest/test_media_source.py index 2b25694de6c28b..6c827e76163491 100644 --- a/tests/components/nest/test_media_source.py +++ b/tests/components/nest/test_media_source.py @@ -256,7 +256,7 @@ async def test_supported_device(hass: HomeAssistant, setup_platform) -> None: assert camera is not None device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -318,7 +318,7 @@ async def test_camera_event( assert camera is not None device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -448,7 +448,7 @@ async def test_event_order( assert camera is not None device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -493,7 +493,7 @@ async def test_multiple_image_events_in_session( assert camera is not None device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -607,7 +607,7 @@ async def test_multiple_clip_preview_events_in_session( assert camera is not None device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -695,7 +695,7 @@ async def test_browse_invalid_device_id( await setup_platform() device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -716,7 +716,7 @@ async def test_browse_invalid_event_id( await setup_platform() device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -739,7 +739,7 @@ async def test_resolve_missing_event_id( await setup_platform() device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -771,7 +771,7 @@ async def test_resolve_invalid_event_id( await setup_platform() device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -819,7 +819,7 @@ async def test_camera_event_clip_preview( assert camera is not None device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -916,7 +916,7 @@ async def test_event_media_render_invalid_event_id( """Test event media API called with an invalid device id.""" await setup_platform() device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -958,7 +958,7 @@ async def test_event_media_failure( assert camera is not None device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -998,7 +998,7 @@ async def test_media_permission_unauthorized( assert camera is not None device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -1034,9 +1034,9 @@ async def test_multiple_devices( await setup_platform() device_registry = dr.async_get(hass) - device1 = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device1 = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device1 - device2 = device_registry.async_get_device({(DOMAIN, device_id2)}) + device2 = device_registry.async_get_device(identifiers={(DOMAIN, device_id2)}) assert device2 # Very no events have been received yet @@ -1121,7 +1121,7 @@ async def test_media_store_persistence( await setup_platform() device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -1174,7 +1174,7 @@ async def test_media_store_persistence( await hass.async_block_till_done() device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -1233,7 +1233,7 @@ async def test_media_store_save_filesystem_error( assert camera is not None device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -1272,7 +1272,7 @@ async def test_media_store_load_filesystem_error( assert camera is not None device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -1322,7 +1322,7 @@ async def test_camera_event_media_eviction( await setup_platform() device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME @@ -1399,7 +1399,7 @@ async def test_camera_image_resize( await setup_platform() device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, DEVICE_ID)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, DEVICE_ID)}) assert device assert device.name == DEVICE_NAME diff --git a/tests/components/netatmo/test_device_trigger.py b/tests/components/netatmo/test_device_trigger.py index c7cbaf4d131f64..ebafd313ff45bf 100644 --- a/tests/components/netatmo/test_device_trigger.py +++ b/tests/components/netatmo/test_device_trigger.py @@ -161,7 +161,7 @@ async def test_if_fires_on_event( }, ) - device = device_registry.async_get_device(set(), {connection}) + device = device_registry.async_get_device(connections={connection}) assert device is not None # Fake that the entity is turning on. @@ -244,7 +244,7 @@ async def test_if_fires_on_event_legacy( }, ) - device = device_registry.async_get_device(set(), {connection}) + device = device_registry.async_get_device(connections={connection}) assert device is not None # Fake that the entity is turning on. @@ -328,7 +328,7 @@ async def test_if_fires_on_event_with_subtype( }, ) - device = device_registry.async_get_device(set(), {connection}) + device = device_registry.async_get_device(connections={connection}) assert device is not None # Fake that the entity is turning on. diff --git a/tests/components/purpleair/test_config_flow.py b/tests/components/purpleair/test_config_flow.py index 503ba23e052d36..b72ac7e3a79854 100644 --- a/tests/components/purpleair/test_config_flow.py +++ b/tests/components/purpleair/test_config_flow.py @@ -288,7 +288,9 @@ async def test_options_remove_sensor( assert result["step_id"] == "remove_sensor" device_registry = dr.async_get(hass) - device_entry = device_registry.async_get_device({(DOMAIN, str(TEST_SENSOR_INDEX1))}) + device_entry = device_registry.async_get_device( + identifiers={(DOMAIN, str(TEST_SENSOR_INDEX1))} + ) result = await hass.config_entries.options.async_configure( result["flow_id"], user_input={"sensor_device_id": device_entry.id}, diff --git a/tests/components/radarr/test_init.py b/tests/components/radarr/test_init.py index 0bd4c538cf69e0..6b602c8c4d1d15 100644 --- a/tests/components/radarr/test_init.py +++ b/tests/components/radarr/test_init.py @@ -51,7 +51,7 @@ async def test_device_info( entry = await setup_integration(hass, aioclient_mock) device_registry = dr.async_get(hass) await hass.async_block_till_done() - device = device_registry.async_get_device({(DOMAIN, entry.entry_id)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, entry.entry_id)}) assert device.configuration_url == "http://192.168.1.189:7887/test" assert device.identifiers == {(DOMAIN, entry.entry_id)} diff --git a/tests/components/rainbird/test_number.py b/tests/components/rainbird/test_number.py index 2ecdfcc537f072..1335a1595d3212 100644 --- a/tests/components/rainbird/test_number.py +++ b/tests/components/rainbird/test_number.py @@ -67,7 +67,7 @@ async def test_set_value( assert await setup_integration() device_registry = dr.async_get(hass) - device = device_registry.async_get_device({(DOMAIN, SERIAL_NUMBER)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, SERIAL_NUMBER)}) assert device assert device.name == "Rain Bird Controller" assert device.model == "ST8x-WiFi" diff --git a/tests/components/renault/__init__.py b/tests/components/renault/__init__.py index 8dd0a1bf15449a..8c47410ce40a46 100644 --- a/tests/components/renault/__init__.py +++ b/tests/components/renault/__init__.py @@ -37,7 +37,9 @@ def check_device_registry( ) -> None: """Ensure that the expected_device is correctly registered.""" assert len(device_registry.devices) == 1 - registry_entry = device_registry.async_get_device(expected_device[ATTR_IDENTIFIERS]) + registry_entry = device_registry.async_get_device( + identifiers=expected_device[ATTR_IDENTIFIERS] + ) assert registry_entry is not None assert registry_entry.identifiers == expected_device[ATTR_IDENTIFIERS] assert registry_entry.manufacturer == expected_device[ATTR_MANUFACTURER] diff --git a/tests/components/renault/test_diagnostics.py b/tests/components/renault/test_diagnostics.py index 31148d4551a5d7..76ea88b4b45828 100644 --- a/tests/components/renault/test_diagnostics.py +++ b/tests/components/renault/test_diagnostics.py @@ -197,7 +197,9 @@ async def test_device_diagnostics( await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() - device = device_registry.async_get_device({(DOMAIN, "VF1AAAAA555777999")}) + device = device_registry.async_get_device( + identifiers={(DOMAIN, "VF1AAAAA555777999")} + ) assert device is not None assert await get_diagnostics_for_device( diff --git a/tests/components/renault/test_services.py b/tests/components/renault/test_services.py index d0ba320c1c6489..58d51eca537155 100644 --- a/tests/components/renault/test_services.py +++ b/tests/components/renault/test_services.py @@ -55,7 +55,7 @@ def get_device_id(hass: HomeAssistant) -> str: """Get device_id.""" device_registry = dr.async_get(hass) identifiers = {(DOMAIN, "VF1AAAAA555777999")} - device = device_registry.async_get_device(identifiers) + device = device_registry.async_get_device(identifiers=identifiers) return device.id @@ -272,7 +272,9 @@ async def test_service_invalid_device_id2( model=extra_vehicle[ATTR_MODEL], sw_version=extra_vehicle[ATTR_SW_VERSION], ) - device_id = device_registry.async_get_device(extra_vehicle[ATTR_IDENTIFIERS]).id + device_id = device_registry.async_get_device( + identifiers=extra_vehicle[ATTR_IDENTIFIERS] + ).id data = {ATTR_VEHICLE: device_id} diff --git a/tests/components/rfxtrx/test_device_action.py b/tests/components/rfxtrx/test_device_action.py index d53ef6a7a02b8d..087a6840c5917d 100644 --- a/tests/components/rfxtrx/test_device_action.py +++ b/tests/components/rfxtrx/test_device_action.py @@ -86,7 +86,9 @@ async def test_get_actions( """Test we get the expected actions from a rfxtrx.""" await setup_entry(hass, {device.code: {}}) - device_entry = device_registry.async_get_device(device.device_identifiers, set()) + device_entry = device_registry.async_get_device( + identifiers=device.device_identifiers + ) assert device_entry # Add alternate identifiers, to make sure we can handle future formats @@ -94,7 +96,9 @@ async def test_get_actions( device_registry.async_update_device( device_entry.id, merge_identifiers={(identifiers[0], "_".join(identifiers[1:]))} ) - device_entry = device_registry.async_get_device(device.device_identifiers, set()) + device_entry = device_registry.async_get_device( + identifiers=device.device_identifiers + ) assert device_entry actions = await async_get_device_automations( @@ -142,7 +146,9 @@ async def test_action( await setup_entry(hass, {device.code: {}}) - device_entry = device_registry.async_get_device(device.device_identifiers, set()) + device_entry = device_registry.async_get_device( + identifiers=device.device_identifiers + ) assert device_entry assert await async_setup_component( @@ -181,8 +187,8 @@ async def test_invalid_action( await setup_entry(hass, {device.code: {}}) - device_identifers: Any = device.device_identifiers - device_entry = device_registry.async_get_device(device_identifers, set()) + device_identifiers: Any = device.device_identifiers + device_entry = device_registry.async_get_device(identifiers=device_identifiers) assert device_entry assert await async_setup_component( diff --git a/tests/components/rfxtrx/test_device_trigger.py b/tests/components/rfxtrx/test_device_trigger.py index 02e9ec87630897..a253810c4c82bc 100644 --- a/tests/components/rfxtrx/test_device_trigger.py +++ b/tests/components/rfxtrx/test_device_trigger.py @@ -87,7 +87,9 @@ async def test_get_triggers( """Test we get the expected triggers from a rfxtrx.""" await setup_entry(hass, {event.code: {}}) - device_entry = device_registry.async_get_device(event.device_identifiers, set()) + device_entry = device_registry.async_get_device( + identifiers=event.device_identifiers + ) assert device_entry # Add alternate identifiers, to make sure we can handle future formats @@ -95,7 +97,9 @@ async def test_get_triggers( device_registry.async_update_device( device_entry.id, merge_identifiers={(identifiers[0], "_".join(identifiers[1:]))} ) - device_entry = device_registry.async_get_device(event.device_identifiers, set()) + device_entry = device_registry.async_get_device( + identifiers=event.device_identifiers + ) assert device_entry expected_triggers = [ @@ -131,7 +135,9 @@ async def test_firing_event( await setup_entry(hass, {event.code: {"fire_event": True}}) - device_entry = device_registry.async_get_device(event.device_identifiers, set()) + device_entry = device_registry.async_get_device( + identifiers=event.device_identifiers + ) assert device_entry calls = async_mock_service(hass, "test", "automation") @@ -175,8 +181,8 @@ async def test_invalid_trigger( await setup_entry(hass, {event.code: {"fire_event": True}}) - device_identifers: Any = event.device_identifiers - device_entry = device_registry.async_get_device(device_identifers, set()) + device_identifiers: Any = event.device_identifiers + device_entry = device_registry.async_get_device(identifiers=device_identifiers) assert device_entry assert await async_setup_component( diff --git a/tests/components/risco/test_alarm_control_panel.py b/tests/components/risco/test_alarm_control_panel.py index 56756aa87fb38f..e49817469b4d2f 100644 --- a/tests/components/risco/test_alarm_control_panel.py +++ b/tests/components/risco/test_alarm_control_panel.py @@ -149,11 +149,11 @@ async def test_cloud_setup( assert registry.async_is_registered(SECOND_CLOUD_ENTITY_ID) registry = dr.async_get(hass) - device = registry.async_get_device({(DOMAIN, TEST_SITE_UUID + "_0")}) + device = registry.async_get_device(identifiers={(DOMAIN, TEST_SITE_UUID + "_0")}) assert device is not None assert device.manufacturer == "Risco" - device = registry.async_get_device({(DOMAIN, TEST_SITE_UUID + "_1")}) + device = registry.async_get_device(identifiers={(DOMAIN, TEST_SITE_UUID + "_1")}) assert device is not None assert device.manufacturer == "Risco" @@ -485,11 +485,15 @@ async def test_local_setup( assert registry.async_is_registered(SECOND_LOCAL_ENTITY_ID) registry = dr.async_get(hass) - device = registry.async_get_device({(DOMAIN, TEST_SITE_UUID + "_0_local")}) + device = registry.async_get_device( + identifiers={(DOMAIN, TEST_SITE_UUID + "_0_local")} + ) assert device is not None assert device.manufacturer == "Risco" - device = registry.async_get_device({(DOMAIN, TEST_SITE_UUID + "_1_local")}) + device = registry.async_get_device( + identifiers={(DOMAIN, TEST_SITE_UUID + "_1_local")} + ) assert device is not None assert device.manufacturer == "Risco" with patch("homeassistant.components.risco.RiscoLocal.disconnect") as mock_close: diff --git a/tests/components/risco/test_binary_sensor.py b/tests/components/risco/test_binary_sensor.py index a223bcd8f74f2b..ee74dbbedc8a28 100644 --- a/tests/components/risco/test_binary_sensor.py +++ b/tests/components/risco/test_binary_sensor.py @@ -41,11 +41,15 @@ async def test_cloud_setup( assert registry.async_is_registered(SECOND_ENTITY_ID) registry = dr.async_get(hass) - device = registry.async_get_device({(DOMAIN, TEST_SITE_UUID + "_zone_0")}) + device = registry.async_get_device( + identifiers={(DOMAIN, TEST_SITE_UUID + "_zone_0")} + ) assert device is not None assert device.manufacturer == "Risco" - device = registry.async_get_device({(DOMAIN, TEST_SITE_UUID + "_zone_1")}) + device = registry.async_get_device( + identifiers={(DOMAIN, TEST_SITE_UUID + "_zone_1")} + ) assert device is not None assert device.manufacturer == "Risco" @@ -99,11 +103,15 @@ async def test_local_setup( assert registry.async_is_registered(SECOND_ALARMED_ENTITY_ID) registry = dr.async_get(hass) - device = registry.async_get_device({(DOMAIN, TEST_SITE_UUID + "_zone_0_local")}) + device = registry.async_get_device( + identifiers={(DOMAIN, TEST_SITE_UUID + "_zone_0_local")} + ) assert device is not None assert device.manufacturer == "Risco" - device = registry.async_get_device({(DOMAIN, TEST_SITE_UUID + "_zone_1_local")}) + device = registry.async_get_device( + identifiers={(DOMAIN, TEST_SITE_UUID + "_zone_1_local")} + ) assert device is not None assert device.manufacturer == "Risco" diff --git a/tests/components/sharkiq/test_vacuum.py b/tests/components/sharkiq/test_vacuum.py index 4a54b900be1894..34b49f5d581ce2 100644 --- a/tests/components/sharkiq/test_vacuum.py +++ b/tests/components/sharkiq/test_vacuum.py @@ -218,7 +218,7 @@ async def test_device_properties( ) -> None: """Test device properties.""" registry = dr.async_get(hass) - device = registry.async_get_device({(DOMAIN, "AC000Wxxxxxxxxx")}) + device = registry.async_get_device(identifiers={(DOMAIN, "AC000Wxxxxxxxxx")}) assert getattr(device, device_property) == target_value diff --git a/tests/components/smartthings/test_binary_sensor.py b/tests/components/smartthings/test_binary_sensor.py index b6f2159ae13edb..d6fe0bd40fc616 100644 --- a/tests/components/smartthings/test_binary_sensor.py +++ b/tests/components/smartthings/test_binary_sensor.py @@ -69,7 +69,7 @@ async def test_entity_and_device_attributes( entry = entity_registry.async_get("binary_sensor.motion_sensor_1_motion") assert entry assert entry.unique_id == f"{device.device_id}.{Attribute.motion}" - entry = device_registry.async_get_device({(DOMAIN, device.device_id)}) + entry = device_registry.async_get_device(identifiers={(DOMAIN, device.device_id)}) assert entry assert entry.configuration_url == "https://account.smartthings.com" assert entry.identifiers == {(DOMAIN, device.device_id)} diff --git a/tests/components/smartthings/test_climate.py b/tests/components/smartthings/test_climate.py index fe917504dcd478..ce875190efb146 100644 --- a/tests/components/smartthings/test_climate.py +++ b/tests/components/smartthings/test_climate.py @@ -580,7 +580,9 @@ async def test_entity_and_device_attributes(hass: HomeAssistant, thermostat) -> assert entry assert entry.unique_id == thermostat.device_id - entry = device_registry.async_get_device({(DOMAIN, thermostat.device_id)}) + entry = device_registry.async_get_device( + identifiers={(DOMAIN, thermostat.device_id)} + ) assert entry assert entry.configuration_url == "https://account.smartthings.com" assert entry.identifiers == {(DOMAIN, thermostat.device_id)} diff --git a/tests/components/smartthings/test_cover.py b/tests/components/smartthings/test_cover.py index f8c21166fe1c02..bdf3cc901a7133 100644 --- a/tests/components/smartthings/test_cover.py +++ b/tests/components/smartthings/test_cover.py @@ -52,7 +52,7 @@ async def test_entity_and_device_attributes( assert entry assert entry.unique_id == device.device_id - entry = device_registry.async_get_device({(DOMAIN, device.device_id)}) + entry = device_registry.async_get_device(identifiers={(DOMAIN, device.device_id)}) assert entry assert entry.configuration_url == "https://account.smartthings.com" assert entry.identifiers == {(DOMAIN, device.device_id)} diff --git a/tests/components/smartthings/test_fan.py b/tests/components/smartthings/test_fan.py index aef9ce319e73a3..ccf4b50fa1bd16 100644 --- a/tests/components/smartthings/test_fan.py +++ b/tests/components/smartthings/test_fan.py @@ -66,7 +66,7 @@ async def test_entity_and_device_attributes( assert entry assert entry.unique_id == device.device_id - entry = device_registry.async_get_device({(DOMAIN, device.device_id)}) + entry = device_registry.async_get_device(identifiers={(DOMAIN, device.device_id)}) assert entry assert entry.configuration_url == "https://account.smartthings.com" assert entry.identifiers == {(DOMAIN, device.device_id)} diff --git a/tests/components/smartthings/test_light.py b/tests/components/smartthings/test_light.py index 0e01910c84a05d..d2d0a133859f35 100644 --- a/tests/components/smartthings/test_light.py +++ b/tests/components/smartthings/test_light.py @@ -128,7 +128,7 @@ async def test_entity_and_device_attributes( assert entry assert entry.unique_id == device.device_id - entry = device_registry.async_get_device({(DOMAIN, device.device_id)}) + entry = device_registry.async_get_device(identifiers={(DOMAIN, device.device_id)}) assert entry assert entry.configuration_url == "https://account.smartthings.com" assert entry.identifiers == {(DOMAIN, device.device_id)} diff --git a/tests/components/smartthings/test_lock.py b/tests/components/smartthings/test_lock.py index 0d237cec132da0..58111087848a0c 100644 --- a/tests/components/smartthings/test_lock.py +++ b/tests/components/smartthings/test_lock.py @@ -42,7 +42,7 @@ async def test_entity_and_device_attributes( assert entry assert entry.unique_id == device.device_id - entry = device_registry.async_get_device({(DOMAIN, device.device_id)}) + entry = device_registry.async_get_device(identifiers={(DOMAIN, device.device_id)}) assert entry assert entry.configuration_url == "https://account.smartthings.com" assert entry.identifiers == {(DOMAIN, device.device_id)} diff --git a/tests/components/smartthings/test_sensor.py b/tests/components/smartthings/test_sensor.py index cc7b67145c1e0f..ab163360778d9d 100644 --- a/tests/components/smartthings/test_sensor.py +++ b/tests/components/smartthings/test_sensor.py @@ -110,7 +110,7 @@ async def test_entity_and_device_attributes( assert entry assert entry.unique_id == f"{device.device_id}.{Attribute.battery}" assert entry.entity_category is EntityCategory.DIAGNOSTIC - entry = device_registry.async_get_device({(DOMAIN, device.device_id)}) + entry = device_registry.async_get_device(identifiers={(DOMAIN, device.device_id)}) assert entry assert entry.configuration_url == "https://account.smartthings.com" assert entry.identifiers == {(DOMAIN, device.device_id)} @@ -151,7 +151,7 @@ async def test_energy_sensors_for_switch_device( assert entry assert entry.unique_id == f"{device.device_id}.{Attribute.energy}" assert entry.entity_category is None - entry = device_registry.async_get_device({(DOMAIN, device.device_id)}) + entry = device_registry.async_get_device(identifiers={(DOMAIN, device.device_id)}) assert entry assert entry.configuration_url == "https://account.smartthings.com" assert entry.identifiers == {(DOMAIN, device.device_id)} @@ -168,7 +168,7 @@ async def test_energy_sensors_for_switch_device( assert entry assert entry.unique_id == f"{device.device_id}.{Attribute.power}" assert entry.entity_category is None - entry = device_registry.async_get_device({(DOMAIN, device.device_id)}) + entry = device_registry.async_get_device(identifiers={(DOMAIN, device.device_id)}) assert entry assert entry.configuration_url == "https://account.smartthings.com" assert entry.identifiers == {(DOMAIN, device.device_id)} @@ -213,7 +213,7 @@ async def test_power_consumption_sensor(hass: HomeAssistant, device_factory) -> entry = entity_registry.async_get("sensor.refrigerator_energy") assert entry assert entry.unique_id == f"{device.device_id}.energy_meter" - entry = device_registry.async_get_device({(DOMAIN, device.device_id)}) + entry = device_registry.async_get_device(identifiers={(DOMAIN, device.device_id)}) assert entry assert entry.configuration_url == "https://account.smartthings.com" assert entry.identifiers == {(DOMAIN, device.device_id)} @@ -231,7 +231,7 @@ async def test_power_consumption_sensor(hass: HomeAssistant, device_factory) -> entry = entity_registry.async_get("sensor.refrigerator_power") assert entry assert entry.unique_id == f"{device.device_id}.power_meter" - entry = device_registry.async_get_device({(DOMAIN, device.device_id)}) + entry = device_registry.async_get_device(identifiers={(DOMAIN, device.device_id)}) assert entry assert entry.configuration_url == "https://account.smartthings.com" assert entry.identifiers == {(DOMAIN, device.device_id)} @@ -263,7 +263,7 @@ async def test_power_consumption_sensor(hass: HomeAssistant, device_factory) -> entry = entity_registry.async_get("sensor.vacuum_energy") assert entry assert entry.unique_id == f"{device.device_id}.energy_meter" - entry = device_registry.async_get_device({(DOMAIN, device.device_id)}) + entry = device_registry.async_get_device(identifiers={(DOMAIN, device.device_id)}) assert entry assert entry.configuration_url == "https://account.smartthings.com" assert entry.identifiers == {(DOMAIN, device.device_id)} diff --git a/tests/components/smartthings/test_switch.py b/tests/components/smartthings/test_switch.py index f90395f0064197..437acb04f56dc6 100644 --- a/tests/components/smartthings/test_switch.py +++ b/tests/components/smartthings/test_switch.py @@ -41,7 +41,7 @@ async def test_entity_and_device_attributes( assert entry assert entry.unique_id == device.device_id - entry = device_registry.async_get_device({(DOMAIN, device.device_id)}) + entry = device_registry.async_get_device(identifiers={(DOMAIN, device.device_id)}) assert entry assert entry.configuration_url == "https://account.smartthings.com" assert entry.identifiers == {(DOMAIN, device.device_id)} diff --git a/tests/components/steam_online/test_init.py b/tests/components/steam_online/test_init.py index 435a5ac6f5afcd..e3f473e01c65ae 100644 --- a/tests/components/steam_online/test_init.py +++ b/tests/components/steam_online/test_init.py @@ -43,7 +43,7 @@ async def test_device_info(hass: HomeAssistant) -> None: await hass.config_entries.async_setup(entry.entry_id) device_registry = dr.async_get(hass) await hass.async_block_till_done() - device = device_registry.async_get_device({(DOMAIN, entry.entry_id)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, entry.entry_id)}) assert device.configuration_url == "https://store.steampowered.com" assert device.entry_type == dr.DeviceEntryType.SERVICE diff --git a/tests/components/steamist/test_init.py b/tests/components/steamist/test_init.py index a40917cfc3c076..0a98f746c4c427 100644 --- a/tests/components/steamist/test_init.py +++ b/tests/components/steamist/test_init.py @@ -105,7 +105,7 @@ def found_devices(self): device_registry = dr.async_get(hass) device_entry = device_registry.async_get_device( - connections={(dr.CONNECTION_NETWORK_MAC, FORMATTED_MAC_ADDRESS)}, identifiers={} + connections={(dr.CONNECTION_NETWORK_MAC, FORMATTED_MAC_ADDRESS)} ) assert isinstance(device_entry, dr.DeviceEntry) assert device_entry.name == DEVICE_NAME diff --git a/tests/components/tasmota/test_common.py b/tests/components/tasmota/test_common.py index 4744d6c2ccff7d..703dd2a1893309 100644 --- a/tests/components/tasmota/test_common.py +++ b/tests/components/tasmota/test_common.py @@ -413,7 +413,7 @@ async def help_test_discovery_removal( # Verify device and entity registry entries are created device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, config1[CONF_MAC])} + connections={(dr.CONNECTION_NETWORK_MAC, config1[CONF_MAC])} ) assert device_entry is not None entity_entry = entity_reg.async_get(f"{domain}.{entity_id}") @@ -436,7 +436,7 @@ async def help_test_discovery_removal( # Verify entity registry entries are cleared device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, config2[CONF_MAC])} + connections={(dr.CONNECTION_NETWORK_MAC, config2[CONF_MAC])} ) assert device_entry is not None entity_entry = entity_reg.async_get(f"{domain}.{entity_id}") @@ -522,7 +522,7 @@ async def help_test_discovery_device_remove( await hass.async_block_till_done() device = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, config[CONF_MAC])} + connections={(dr.CONNECTION_NETWORK_MAC, config[CONF_MAC])} ) assert device is not None assert entity_reg.async_get_entity_id(domain, "tasmota", unique_id) @@ -531,7 +531,7 @@ async def help_test_discovery_device_remove( await hass.async_block_till_done() device = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, config[CONF_MAC])} + connections={(dr.CONNECTION_NETWORK_MAC, config[CONF_MAC])} ) assert device is None assert not entity_reg.async_get_entity_id(domain, "tasmota", unique_id) diff --git a/tests/components/tasmota/test_device_trigger.py b/tests/components/tasmota/test_device_trigger.py index 880f4ed0e7585e..ffff4b1b8b01b2 100644 --- a/tests/components/tasmota/test_device_trigger.py +++ b/tests/components/tasmota/test_device_trigger.py @@ -49,7 +49,7 @@ async def test_get_triggers_btn( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) expected_triggers = [ { @@ -93,7 +93,7 @@ async def test_get_triggers_swc( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) expected_triggers = [ { @@ -129,7 +129,7 @@ async def test_get_unknown_triggers( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert await async_setup_component( @@ -178,7 +178,7 @@ async def test_get_non_existing_triggers( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) triggers = await async_get_device_automations( hass, DeviceAutomationType.TRIGGER, device_entry.id @@ -210,7 +210,7 @@ async def test_discover_bad_triggers( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) triggers = await async_get_device_automations( hass, DeviceAutomationType.TRIGGER, device_entry.id @@ -246,7 +246,7 @@ def is_active(self): await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) triggers = await async_get_device_automations( hass, DeviceAutomationType.TRIGGER, device_entry.id @@ -299,7 +299,7 @@ async def test_update_remove_triggers( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) expected_triggers1 = [ @@ -365,7 +365,7 @@ async def test_if_fires_on_mqtt_message_btn( async_fire_mqtt_message(hass, f"{DEFAULT_PREFIX}/{mac}/config", json.dumps(config)) await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert await async_setup_component( @@ -437,7 +437,7 @@ async def test_if_fires_on_mqtt_message_swc( async_fire_mqtt_message(hass, f"{DEFAULT_PREFIX}/{mac}/config", json.dumps(config)) await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert await async_setup_component( @@ -535,7 +535,7 @@ async def test_if_fires_on_mqtt_message_late_discover( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert await async_setup_component( @@ -611,7 +611,7 @@ async def test_if_fires_on_mqtt_message_after_update( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert await async_setup_component( @@ -692,7 +692,7 @@ async def test_no_resubscribe_same_topic( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert await async_setup_component( @@ -740,7 +740,7 @@ async def test_not_fires_on_mqtt_message_after_remove_by_mqtt( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert await async_setup_component( @@ -817,7 +817,7 @@ async def test_not_fires_on_mqtt_message_after_remove_from_registry( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert await async_setup_component( @@ -876,7 +876,7 @@ async def test_attach_remove( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) calls = [] @@ -939,7 +939,7 @@ async def test_attach_remove_late( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) calls = [] @@ -1012,7 +1012,7 @@ async def test_attach_remove_late2( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) calls = [] @@ -1066,7 +1066,7 @@ async def test_attach_remove_unknown1( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) remove = await async_initialize_triggers( @@ -1119,7 +1119,7 @@ async def test_attach_unknown_remove_device_from_registry( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) await async_initialize_triggers( @@ -1160,7 +1160,7 @@ async def test_attach_remove_config_entry( await hass.async_block_till_done() device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) calls = [] diff --git a/tests/components/tasmota/test_discovery.py b/tests/components/tasmota/test_discovery.py index 74014c9110220d..9a3f4f91ec754b 100644 --- a/tests/components/tasmota/test_discovery.py +++ b/tests/components/tasmota/test_discovery.py @@ -140,7 +140,7 @@ async def test_correct_config_discovery( # Verify device and registry entries are created device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is not None entity_entry = entity_reg.async_get("switch.test") @@ -174,7 +174,7 @@ async def test_device_discover( # Verify device and registry entries are created device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is not None assert device_entry.configuration_url == f"http://{config['ip']}/" @@ -205,7 +205,7 @@ async def test_device_discover_deprecated( # Verify device and registry entries are created device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is not None assert device_entry.manufacturer == "Tasmota" @@ -238,7 +238,7 @@ async def test_device_update( # Verify device entry is created device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is not None @@ -256,7 +256,7 @@ async def test_device_update( # Verify device entry is updated device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is not None assert device_entry.model == "Another model" @@ -285,7 +285,7 @@ async def test_device_remove( # Verify device entry is created device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is not None @@ -298,7 +298,7 @@ async def test_device_remove( # Verify device entry is removed device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is None @@ -334,7 +334,7 @@ async def test_device_remove_multiple_config_entries_1( # Verify device entry is created device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is not None assert device_entry.config_entries == {tasmota_entry.entry_id, mock_entry.entry_id} @@ -348,7 +348,7 @@ async def test_device_remove_multiple_config_entries_1( # Verify device entry is not removed device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is not None assert device_entry.config_entries == {mock_entry.entry_id} @@ -390,7 +390,7 @@ async def test_device_remove_multiple_config_entries_2( # Verify device entry is created device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is not None assert device_entry.config_entries == {tasmota_entry.entry_id, mock_entry.entry_id} @@ -404,7 +404,7 @@ async def test_device_remove_multiple_config_entries_2( # Verify device entry is not removed device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is not None assert device_entry.config_entries == {tasmota_entry.entry_id} @@ -440,7 +440,7 @@ async def test_device_remove_stale( # Verify device entry was created device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is not None @@ -449,7 +449,7 @@ async def test_device_remove_stale( # Verify device entry is removed device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is None @@ -475,7 +475,7 @@ async def test_device_rediscover( # Verify device entry is created device_entry1 = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry1 is not None @@ -488,7 +488,7 @@ async def test_device_rediscover( # Verify device entry is removed device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is None @@ -501,7 +501,7 @@ async def test_device_rediscover( # Verify device entry is created, and id is reused device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is not None assert device_entry1.id == device_entry.id @@ -602,7 +602,7 @@ async def test_same_topic( # Verify device registry entries are created for both devices for config in configs[0:2]: device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, config["mac"])} + connections={(dr.CONNECTION_NETWORK_MAC, config["mac"])} ) assert device_entry is not None assert device_entry.configuration_url == f"http://{config['ip']}/" @@ -613,11 +613,11 @@ async def test_same_topic( # Verify entities are created only for the first device device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, configs[0]["mac"])} + connections={(dr.CONNECTION_NETWORK_MAC, configs[0]["mac"])} ) assert len(er.async_entries_for_device(entity_reg, device_entry.id, True)) == 1 device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, configs[1]["mac"])} + connections={(dr.CONNECTION_NETWORK_MAC, configs[1]["mac"])} ) assert len(er.async_entries_for_device(entity_reg, device_entry.id, True)) == 0 @@ -637,7 +637,7 @@ async def test_same_topic( # Verify device registry entries was created device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, configs[2]["mac"])} + connections={(dr.CONNECTION_NETWORK_MAC, configs[2]["mac"])} ) assert device_entry is not None assert device_entry.configuration_url == f"http://{configs[2]['ip']}/" @@ -648,7 +648,7 @@ async def test_same_topic( # Verify no entities were created device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, configs[2]["mac"])} + connections={(dr.CONNECTION_NETWORK_MAC, configs[2]["mac"])} ) assert len(er.async_entries_for_device(entity_reg, device_entry.id, True)) == 0 @@ -667,7 +667,7 @@ async def test_same_topic( # Verify entities are created also for the third device device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, configs[2]["mac"])} + connections={(dr.CONNECTION_NETWORK_MAC, configs[2]["mac"])} ) assert len(er.async_entries_for_device(entity_reg, device_entry.id, True)) == 1 @@ -686,7 +686,7 @@ async def test_same_topic( # Verify entities are created also for the second device device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, configs[1]["mac"])} + connections={(dr.CONNECTION_NETWORK_MAC, configs[1]["mac"])} ) assert len(er.async_entries_for_device(entity_reg, device_entry.id, True)) == 1 @@ -716,7 +716,7 @@ async def test_topic_no_prefix( # Verify device registry entry is created device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, config["mac"])} + connections={(dr.CONNECTION_NETWORK_MAC, config["mac"])} ) assert device_entry is not None assert device_entry.configuration_url == f"http://{config['ip']}/" @@ -727,7 +727,7 @@ async def test_topic_no_prefix( # Verify entities are not created device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, config["mac"])} + connections={(dr.CONNECTION_NETWORK_MAC, config["mac"])} ) assert len(er.async_entries_for_device(entity_reg, device_entry.id, True)) == 0 @@ -747,7 +747,7 @@ async def test_topic_no_prefix( # Verify entities are created device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, config["mac"])} + connections={(dr.CONNECTION_NETWORK_MAC, config["mac"])} ) assert len(er.async_entries_for_device(entity_reg, device_entry.id, True)) == 1 diff --git a/tests/components/tasmota/test_init.py b/tests/components/tasmota/test_init.py index b19e8e5110303b..09467b893e08de 100644 --- a/tests/components/tasmota/test_init.py +++ b/tests/components/tasmota/test_init.py @@ -44,7 +44,7 @@ async def test_device_remove( # Verify device entry is created device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is not None @@ -53,7 +53,7 @@ async def test_device_remove( # Verify device entry is removed device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is None @@ -104,7 +104,7 @@ async def async_remove_config_entry_device(hass, config_entry, device_entry): # Verify device entry is removed device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is None @@ -135,7 +135,7 @@ async def test_device_remove_stale_tasmota_device( # Verify device entry is removed device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is None @@ -161,7 +161,7 @@ async def test_tasmota_ws_remove_discovered_device( # Verify device entry is created device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is not None @@ -180,6 +180,6 @@ async def test_tasmota_ws_remove_discovered_device( # Verify device entry is cleared device_entry = device_reg.async_get_device( - set(), {(dr.CONNECTION_NETWORK_MAC, mac)} + connections={(dr.CONNECTION_NETWORK_MAC, mac)} ) assert device_entry is None diff --git a/tests/components/twinkly/test_light.py b/tests/components/twinkly/test_light.py index 278c2549b457e7..f66c82dc2eda34 100644 --- a/tests/components/twinkly/test_light.py +++ b/tests/components/twinkly/test_light.py @@ -342,7 +342,7 @@ async def _create_entries( entity_id = entity_registry.async_get_entity_id("light", TWINKLY_DOMAIN, client.id) entity_entry = entity_registry.async_get(entity_id) - device = device_registry.async_get_device({(TWINKLY_DOMAIN, client.id)}) + device = device_registry.async_get_device(identifiers={(TWINKLY_DOMAIN, client.id)}) assert entity_entry is not None assert device is not None diff --git a/tests/components/velbus/test_init.py b/tests/components/velbus/test_init.py index ce0a08f18ffe51..0a1a727abcf989 100644 --- a/tests/components/velbus/test_init.py +++ b/tests/components/velbus/test_init.py @@ -45,17 +45,17 @@ async def test_device_identifier_migration( sw_version="module_sw_version", ) assert device_registry.async_get_device( - original_identifiers # type: ignore[arg-type] + identifiers=original_identifiers # type: ignore[arg-type] ) - assert not device_registry.async_get_device(target_identifiers) + assert not device_registry.async_get_device(identifiers=target_identifiers) await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert not device_registry.async_get_device( - original_identifiers # type: ignore[arg-type] + identifiers=original_identifiers # type: ignore[arg-type] ) - device_entry = device_registry.async_get_device(target_identifiers) + device_entry = device_registry.async_get_device(identifiers=target_identifiers) assert device_entry assert device_entry.name == "channel_name" assert device_entry.manufacturer == "Velleman" diff --git a/tests/components/voip/test_devices.py b/tests/components/voip/test_devices.py index c421a08ccf89ec..189dff498394a6 100644 --- a/tests/components/voip/test_devices.py +++ b/tests/components/voip/test_devices.py @@ -19,7 +19,9 @@ async def test_device_registry_info( voip_device = voip_devices.async_get_or_create(call_info) assert not voip_device.async_allow_call(hass) - device = device_registry.async_get_device({(DOMAIN, call_info.caller_ip)}) + device = device_registry.async_get_device( + identifiers={(DOMAIN, call_info.caller_ip)} + ) assert device is not None assert device.name == call_info.caller_ip assert device.manufacturer == "Grandstream" @@ -32,7 +34,9 @@ async def test_device_registry_info( assert not voip_device.async_allow_call(hass) - device = device_registry.async_get_device({(DOMAIN, call_info.caller_ip)}) + device = device_registry.async_get_device( + identifiers={(DOMAIN, call_info.caller_ip)} + ) assert device.sw_version == "2.0.0.0" @@ -47,7 +51,9 @@ async def test_device_registry_info_from_unknown_phone( voip_device = voip_devices.async_get_or_create(call_info) assert not voip_device.async_allow_call(hass) - device = device_registry.async_get_device({(DOMAIN, call_info.caller_ip)}) + device = device_registry.async_get_device( + identifiers={(DOMAIN, call_info.caller_ip)} + ) assert device.manufacturer is None assert device.model == "Unknown" assert device.sw_version is None diff --git a/tests/components/webostv/test_media_player.py b/tests/components/webostv/test_media_player.py index fec1bf7a04a852..c027b57acf83bd 100644 --- a/tests/components/webostv/test_media_player.py +++ b/tests/components/webostv/test_media_player.py @@ -279,7 +279,7 @@ async def test_device_info_startup_off( assert hass.states.get(ENTITY_ID).state == STATE_OFF - device = device_registry.async_get_device({(DOMAIN, entry.unique_id)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, entry.unique_id)}) assert device assert device.identifiers == {(DOMAIN, entry.unique_id)} @@ -326,7 +326,7 @@ async def test_entity_attributes( assert attrs[ATTR_MEDIA_TITLE] == "Channel Name 2" # Device Info - device = device_registry.async_get_device({(DOMAIN, entry.unique_id)}) + device = device_registry.async_get_device(identifiers={(DOMAIN, entry.unique_id)}) assert device assert device.identifiers == {(DOMAIN, entry.unique_id)} diff --git a/tests/components/xiaomi_ble/test_device_trigger.py b/tests/components/xiaomi_ble/test_device_trigger.py index 85454959cf44d4..eba850e61e9b1a 100644 --- a/tests/components/xiaomi_ble/test_device_trigger.py +++ b/tests/components/xiaomi_ble/test_device_trigger.py @@ -99,7 +99,7 @@ async def test_get_triggers( await hass.async_block_till_done() assert len(events) == 1 - device = device_registry.async_get_device({get_device_id(mac)}) + device = device_registry.async_get_device(identifiers={get_device_id(mac)}) assert device expected_trigger = { CONF_PLATFORM: "device", @@ -196,7 +196,7 @@ async def test_if_fires_on_motion_detected( # wait for the event await hass.async_block_till_done() - device = device_registry.async_get_device({get_device_id(mac)}) + device = device_registry.async_get_device(identifiers={get_device_id(mac)}) device_id = device.id assert await async_setup_component( @@ -256,7 +256,7 @@ async def test_automation_with_invalid_trigger_type( # wait for the event await hass.async_block_till_done() - device = device_registry.async_get_device({get_device_id(mac)}) + device = device_registry.async_get_device(identifiers={get_device_id(mac)}) device_id = device.id assert await async_setup_component( @@ -305,7 +305,7 @@ async def test_automation_with_invalid_trigger_event_property( # wait for the event await hass.async_block_till_done() - device = device_registry.async_get_device({get_device_id(mac)}) + device = device_registry.async_get_device(identifiers={get_device_id(mac)}) device_id = device.id assert await async_setup_component( diff --git a/tests/components/yolink/test_device_trigger.py b/tests/components/yolink/test_device_trigger.py index e0ef37c1b75bd6..0e258d0e1c7ba7 100644 --- a/tests/components/yolink/test_device_trigger.py +++ b/tests/components/yolink/test_device_trigger.py @@ -154,7 +154,7 @@ async def test_if_fires_on_event( }, ) - device = device_registry.async_get_device(set(), {connection}) + device = device_registry.async_get_device(connections={connection}) assert device is not None # Fake remote button long press. hass.bus.async_fire( diff --git a/tests/components/youtube/test_init.py b/tests/components/youtube/test_init.py index 02df1b0e32e2e2..bd3babdc383d3b 100644 --- a/tests/components/youtube/test_init.py +++ b/tests/components/youtube/test_init.py @@ -126,7 +126,7 @@ async def test_device_info( entry = hass.config_entries.async_entries(DOMAIN)[0] channel_id = entry.options[CONF_CHANNELS][0] device = device_registry.async_get_device( - {(DOMAIN, f"{entry.entry_id}_{channel_id}")} + identifiers={(DOMAIN, f"{entry.entry_id}_{channel_id}")} ) assert device.entry_type is dr.DeviceEntryType.SERVICE diff --git a/tests/components/zha/test_device_action.py b/tests/components/zha/test_device_action.py index d938512981fdcd..46cdff180e9b72 100644 --- a/tests/components/zha/test_device_action.py +++ b/tests/components/zha/test_device_action.py @@ -113,7 +113,9 @@ async def test_get_actions(hass: HomeAssistant, device_ias) -> None: ieee_address = str(device_ias[0].ieee) ha_device_registry = dr.async_get(hass) - reg_device = ha_device_registry.async_get_device({(DOMAIN, ieee_address)}) + reg_device = ha_device_registry.async_get_device( + identifiers={(DOMAIN, ieee_address)} + ) ha_entity_registry = er.async_get(hass) siren_level_select = ha_entity_registry.async_get( "select.fakemanufacturer_fakemodel_default_siren_level" @@ -175,7 +177,7 @@ async def test_get_inovelli_actions(hass: HomeAssistant, device_inovelli) -> Non inovelli_ieee_address = str(device_inovelli[0].ieee) ha_device_registry = dr.async_get(hass) inovelli_reg_device = ha_device_registry.async_get_device( - {(DOMAIN, inovelli_ieee_address)} + identifiers={(DOMAIN, inovelli_ieee_address)} ) ha_entity_registry = er.async_get(hass) inovelli_button = ha_entity_registry.async_get("button.inovelli_vzm31_sn_identify") @@ -265,9 +267,11 @@ async def test_action(hass: HomeAssistant, device_ias, device_inovelli) -> None: inovelli_ieee_address = str(inovelli_zha_device.ieee) ha_device_registry = dr.async_get(hass) - reg_device = ha_device_registry.async_get_device({(DOMAIN, ieee_address)}) + reg_device = ha_device_registry.async_get_device( + identifiers={(DOMAIN, ieee_address)} + ) inovelli_reg_device = ha_device_registry.async_get_device( - {(DOMAIN, inovelli_ieee_address)} + identifiers={(DOMAIN, inovelli_ieee_address)} ) cluster = inovelli_zigpy_device.endpoints[1].in_clusters[0xFC31] diff --git a/tests/components/zha/test_device_trigger.py b/tests/components/zha/test_device_trigger.py index 85e012c5bfb24b..22f62cb977a871 100644 --- a/tests/components/zha/test_device_trigger.py +++ b/tests/components/zha/test_device_trigger.py @@ -105,7 +105,9 @@ async def test_triggers(hass: HomeAssistant, mock_devices) -> None: ieee_address = str(zha_device.ieee) ha_device_registry = dr.async_get(hass) - reg_device = ha_device_registry.async_get_device({("zha", ieee_address)}) + reg_device = ha_device_registry.async_get_device( + identifiers={("zha", ieee_address)} + ) triggers = await async_get_device_automations( hass, DeviceAutomationType.TRIGGER, reg_device.id @@ -171,7 +173,9 @@ async def test_no_triggers(hass: HomeAssistant, mock_devices) -> None: ieee_address = str(zha_device.ieee) ha_device_registry = dr.async_get(hass) - reg_device = ha_device_registry.async_get_device({("zha", ieee_address)}) + reg_device = ha_device_registry.async_get_device( + identifiers={("zha", ieee_address)} + ) triggers = await async_get_device_automations( hass, DeviceAutomationType.TRIGGER, reg_device.id @@ -203,7 +207,9 @@ async def test_if_fires_on_event(hass: HomeAssistant, mock_devices, calls) -> No ieee_address = str(zha_device.ieee) ha_device_registry = dr.async_get(hass) - reg_device = ha_device_registry.async_get_device({("zha", ieee_address)}) + reg_device = ha_device_registry.async_get_device( + identifiers={("zha", ieee_address)} + ) assert await async_setup_component( hass, @@ -312,7 +318,9 @@ async def test_exception_no_triggers( ieee_address = str(zha_device.ieee) ha_device_registry = dr.async_get(hass) - reg_device = ha_device_registry.async_get_device({("zha", ieee_address)}) + reg_device = ha_device_registry.async_get_device( + identifiers={("zha", ieee_address)} + ) await async_setup_component( hass, @@ -359,7 +367,9 @@ async def test_exception_bad_trigger( ieee_address = str(zha_device.ieee) ha_device_registry = dr.async_get(hass) - reg_device = ha_device_registry.async_get_device({("zha", ieee_address)}) + reg_device = ha_device_registry.async_get_device( + identifiers={("zha", ieee_address)} + ) await async_setup_component( hass, diff --git a/tests/components/zha/test_diagnostics.py b/tests/components/zha/test_diagnostics.py index 5ec555d88dfc93..0bb06ea723b2ae 100644 --- a/tests/components/zha/test_diagnostics.py +++ b/tests/components/zha/test_diagnostics.py @@ -94,7 +94,7 @@ async def test_diagnostics_for_device( zha_device: ZHADevice = await zha_device_joined(zigpy_device) dev_reg = async_get(hass) - device = dev_reg.async_get_device({("zha", str(zha_device.ieee))}) + device = dev_reg.async_get_device(identifiers={("zha", str(zha_device.ieee))}) assert device diagnostics_data = await get_diagnostics_for_device( hass, hass_client, config_entry, device diff --git a/tests/components/zha/test_logbook.py b/tests/components/zha/test_logbook.py index 3d20749baacfee..44495cf0e15f42 100644 --- a/tests/components/zha/test_logbook.py +++ b/tests/components/zha/test_logbook.py @@ -78,7 +78,9 @@ async def test_zha_logbook_event_device_with_triggers( ieee_address = str(zha_device.ieee) ha_device_registry = dr.async_get(hass) - reg_device = ha_device_registry.async_get_device({("zha", ieee_address)}) + reg_device = ha_device_registry.async_get_device( + identifiers={("zha", ieee_address)} + ) hass.config.components.add("recorder") assert await async_setup_component(hass, "logbook", {}) @@ -154,7 +156,9 @@ async def test_zha_logbook_event_device_no_triggers( zigpy_device, zha_device = mock_devices ieee_address = str(zha_device.ieee) ha_device_registry = dr.async_get(hass) - reg_device = ha_device_registry.async_get_device({("zha", ieee_address)}) + reg_device = ha_device_registry.async_get_device( + identifiers={("zha", ieee_address)} + ) hass.config.components.add("recorder") assert await async_setup_component(hass, "logbook", {}) diff --git a/tests/components/zwave_js/test_api.py b/tests/components/zwave_js/test_api.py index c6a0f7a845d51e..ebdf21124357fe 100644 --- a/tests/components/zwave_js/test_api.py +++ b/tests/components/zwave_js/test_api.py @@ -94,7 +94,7 @@ def get_device(hass: HomeAssistant, node): """Get device ID for a node.""" dev_reg = dr.async_get(hass) device_id = get_device_id(node.client.driver, node) - return dev_reg.async_get_device({device_id}) + return dev_reg.async_get_device(identifiers={device_id}) async def test_no_driver( @@ -462,7 +462,7 @@ async def test_node_comments( ws_client = await hass_ws_client(hass) dev_reg = dr.async_get(hass) - device = dev_reg.async_get_device({(DOMAIN, "3245146787-35")}) + device = dev_reg.async_get_device(identifiers={(DOMAIN, "3245146787-35")}) assert device await ws_client.send_json( diff --git a/tests/components/zwave_js/test_device_action.py b/tests/components/zwave_js/test_device_action.py index ccb65c1d8fa216..b5d4149a5260d1 100644 --- a/tests/components/zwave_js/test_device_action.py +++ b/tests/components/zwave_js/test_device_action.py @@ -32,7 +32,7 @@ async def test_get_actions( node = lock_schlage_be469 driver = client.driver assert driver - device = device_registry.async_get_device({get_device_id(driver, node)}) + device = device_registry.async_get_device(identifiers={get_device_id(driver, node)}) assert device expected_actions = [ { @@ -94,7 +94,7 @@ async def test_get_actions( # Test that we don't return actions for a controller node device = device_registry.async_get_device( - {get_device_id(driver, client.driver.controller.nodes[1])} + identifiers={get_device_id(driver, client.driver.controller.nodes[1])} ) assert device assert ( @@ -114,7 +114,7 @@ async def test_get_actions_meter( node = aeon_smart_switch_6 driver = client.driver assert driver - device = device_registry.async_get_device({get_device_id(driver, node)}) + device = device_registry.async_get_device(identifiers={get_device_id(driver, node)}) assert device actions = await async_get_device_automations( hass, DeviceAutomationType.ACTION, device.id @@ -135,7 +135,7 @@ async def test_actions( driver = client.driver assert driver device_id = get_device_id(driver, node) - device = device_registry.async_get_device({device_id}) + device = device_registry.async_get_device(identifiers={device_id}) assert device assert await async_setup_component( @@ -285,7 +285,7 @@ async def test_actions_multiple_calls( driver = client.driver assert driver device_id = get_device_id(driver, node) - device = device_registry.async_get_device({device_id}) + device = device_registry.async_get_device(identifiers={device_id}) assert device assert await async_setup_component( @@ -332,7 +332,7 @@ async def test_lock_actions( driver = client.driver assert driver device_id = get_device_id(driver, node) - device = device_registry.async_get_device({device_id}) + device = device_registry.async_get_device(identifiers={device_id}) assert device assert await async_setup_component( @@ -403,7 +403,7 @@ async def test_reset_meter_action( driver = client.driver assert driver device_id = get_device_id(driver, node) - device = device_registry.async_get_device({device_id}) + device = device_registry.async_get_device(identifiers={device_id}) assert device assert await async_setup_component( @@ -448,7 +448,7 @@ async def test_get_action_capabilities( ) -> None: """Test we get the expected action capabilities.""" device = device_registry.async_get_device( - {get_device_id(client.driver, climate_radio_thermostat_ct100_plus)} + identifiers={get_device_id(client.driver, climate_radio_thermostat_ct100_plus)} ) assert device @@ -668,7 +668,7 @@ async def test_get_action_capabilities_meter_triggers( node = aeon_smart_switch_6 driver = client.driver assert driver - device = device_registry.async_get_device({get_device_id(driver, node)}) + device = device_registry.async_get_device(identifiers={get_device_id(driver, node)}) assert device capabilities = await device_action.async_get_action_capabilities( hass, @@ -724,7 +724,7 @@ async def test_unavailable_entity_actions( node = lock_schlage_be469 driver = client.driver assert driver - device = device_registry.async_get_device({get_device_id(driver, node)}) + device = device_registry.async_get_device(identifiers={get_device_id(driver, node)}) assert device actions = await async_get_device_automations( hass, DeviceAutomationType.ACTION, device.id diff --git a/tests/components/zwave_js/test_device_condition.py b/tests/components/zwave_js/test_device_condition.py index 11213d9c37543c..f7aacec36ac5d3 100644 --- a/tests/components/zwave_js/test_device_condition.py +++ b/tests/components/zwave_js/test_device_condition.py @@ -42,7 +42,7 @@ async def test_get_conditions( ) -> None: """Test we get the expected onditions from a zwave_js.""" device = device_registry.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device config_value = list(lock_schlage_be469.get_configuration_values().values())[0] @@ -82,7 +82,7 @@ async def test_get_conditions( # Test that we don't return actions for a controller node device = device_registry.async_get_device( - {get_device_id(client.driver, client.driver.controller.nodes[1])} + identifiers={get_device_id(client.driver, client.driver.controller.nodes[1])} ) assert device assert ( @@ -103,7 +103,7 @@ async def test_node_status_state( ) -> None: """Test for node_status conditions.""" device = device_registry.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device @@ -268,7 +268,7 @@ async def test_config_parameter_state( ) -> None: """Test for config_parameter conditions.""" device = device_registry.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device @@ -388,7 +388,7 @@ async def test_value_state( ) -> None: """Test for value conditions.""" device = device_registry.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device @@ -439,7 +439,7 @@ async def test_get_condition_capabilities_node_status( ) -> None: """Test we don't get capabilities from a node_status condition.""" device = device_registry.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device @@ -479,7 +479,7 @@ async def test_get_condition_capabilities_value( ) -> None: """Test we get the expected capabilities from a value condition.""" device = device_registry.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device @@ -532,7 +532,7 @@ async def test_get_condition_capabilities_config_parameter( """Test we get the expected capabilities from a config_parameter condition.""" node = climate_radio_thermostat_ct100_plus device = device_registry.async_get_device( - {get_device_id(client.driver, climate_radio_thermostat_ct100_plus)} + identifiers={get_device_id(client.driver, climate_radio_thermostat_ct100_plus)} ) assert device @@ -617,7 +617,7 @@ async def test_failure_scenarios( ) -> None: """Test failure scenarios.""" device = device_registry.async_get_device( - {get_device_id(client.driver, hank_binary_switch)} + identifiers={get_device_id(client.driver, hank_binary_switch)} ) assert device diff --git a/tests/components/zwave_js/test_device_trigger.py b/tests/components/zwave_js/test_device_trigger.py index 8209564579c33f..fd091b2bfe78a7 100644 --- a/tests/components/zwave_js/test_device_trigger.py +++ b/tests/components/zwave_js/test_device_trigger.py @@ -41,7 +41,7 @@ async def test_no_controller_triggers(hass: HomeAssistant, client, integration) """Test that we do not get triggers for the controller.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, client.driver.controller.nodes[1])} + identifiers={get_device_id(client.driver, client.driver.controller.nodes[1])} ) assert device assert ( @@ -58,7 +58,7 @@ async def test_get_notification_notification_triggers( """Test we get the expected triggers from a zwave_js device with the Notification CC.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device expected_trigger = { @@ -82,7 +82,7 @@ async def test_if_notification_notification_fires( node: Node = lock_schlage_be469 dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device @@ -178,7 +178,7 @@ async def test_get_trigger_capabilities_notification_notification( """Test we get the expected capabilities from a notification.notification trigger.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device capabilities = await device_trigger.async_get_trigger_capabilities( @@ -212,7 +212,7 @@ async def test_if_entry_control_notification_fires( node: Node = lock_schlage_be469 dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device @@ -307,7 +307,7 @@ async def test_get_trigger_capabilities_entry_control_notification( """Test we get the expected capabilities from a notification.entry_control trigger.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device capabilities = await device_trigger.async_get_trigger_capabilities( @@ -338,7 +338,7 @@ async def test_get_node_status_triggers( """Test we get the expected triggers from a device with node status sensor enabled.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device ent_reg = async_get_ent_reg(hass) @@ -370,7 +370,7 @@ async def test_if_node_status_change_fires( node: Node = lock_schlage_be469 dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device ent_reg = async_get_ent_reg(hass) @@ -448,7 +448,7 @@ async def test_get_trigger_capabilities_node_status( """Test we get the expected capabilities from a node_status trigger.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device ent_reg = async_get_ent_reg(hass) @@ -506,7 +506,7 @@ async def test_get_basic_value_notification_triggers( """Test we get the expected triggers from a zwave_js device with the Basic CC.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, ge_in_wall_dimmer_switch)} + identifiers={get_device_id(client.driver, ge_in_wall_dimmer_switch)} ) assert device expected_trigger = { @@ -534,7 +534,7 @@ async def test_if_basic_value_notification_fires( node: Node = ge_in_wall_dimmer_switch dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, ge_in_wall_dimmer_switch)} + identifiers={get_device_id(client.driver, ge_in_wall_dimmer_switch)} ) assert device @@ -645,7 +645,7 @@ async def test_get_trigger_capabilities_basic_value_notification( """Test we get the expected capabilities from a value_notification.basic trigger.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, ge_in_wall_dimmer_switch)} + identifiers={get_device_id(client.driver, ge_in_wall_dimmer_switch)} ) assert device capabilities = await device_trigger.async_get_trigger_capabilities( @@ -683,7 +683,7 @@ async def test_get_central_scene_value_notification_triggers( """Test we get the expected triggers from a zwave_js device with the Central Scene CC.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, wallmote_central_scene)} + identifiers={get_device_id(client.driver, wallmote_central_scene)} ) assert device expected_trigger = { @@ -711,7 +711,7 @@ async def test_if_central_scene_value_notification_fires( node: Node = wallmote_central_scene dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, wallmote_central_scene)} + identifiers={get_device_id(client.driver, wallmote_central_scene)} ) assert device @@ -828,7 +828,7 @@ async def test_get_trigger_capabilities_central_scene_value_notification( """Test we get the expected capabilities from a value_notification.central_scene trigger.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, wallmote_central_scene)} + identifiers={get_device_id(client.driver, wallmote_central_scene)} ) assert device capabilities = await device_trigger.async_get_trigger_capabilities( @@ -865,7 +865,7 @@ async def test_get_scene_activation_value_notification_triggers( """Test we get the expected triggers from a zwave_js device with the SceneActivation CC.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, hank_binary_switch)} + identifiers={get_device_id(client.driver, hank_binary_switch)} ) assert device expected_trigger = { @@ -893,7 +893,7 @@ async def test_if_scene_activation_value_notification_fires( node: Node = hank_binary_switch dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, hank_binary_switch)} + identifiers={get_device_id(client.driver, hank_binary_switch)} ) assert device @@ -1004,7 +1004,7 @@ async def test_get_trigger_capabilities_scene_activation_value_notification( """Test we get the expected capabilities from a value_notification.scene_activation trigger.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, hank_binary_switch)} + identifiers={get_device_id(client.driver, hank_binary_switch)} ) assert device capabilities = await device_trigger.async_get_trigger_capabilities( @@ -1042,7 +1042,7 @@ async def test_get_value_updated_value_triggers( """Test we get the zwave_js.value_updated.value trigger from a zwave_js device.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device expected_trigger = { @@ -1065,7 +1065,7 @@ async def test_if_value_updated_value_fires( node: Node = lock_schlage_be469 dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device @@ -1157,7 +1157,7 @@ async def test_value_updated_value_no_driver( node: Node = lock_schlage_be469 dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device driver = client.driver @@ -1227,7 +1227,7 @@ async def test_get_trigger_capabilities_value_updated_value( """Test we get the expected capabilities from a zwave_js.value_updated.value trigger.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device capabilities = await device_trigger.async_get_trigger_capabilities( @@ -1278,7 +1278,7 @@ async def test_get_value_updated_config_parameter_triggers( """Test we get the zwave_js.value_updated.config_parameter trigger from a zwave_js device.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device expected_trigger = { @@ -1306,7 +1306,7 @@ async def test_if_value_updated_config_parameter_fires( node: Node = lock_schlage_be469 dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device @@ -1376,7 +1376,7 @@ async def test_get_trigger_capabilities_value_updated_config_parameter_range( """Test we get the expected capabilities from a range zwave_js.value_updated.config_parameter trigger.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device capabilities = await device_trigger.async_get_trigger_capabilities( @@ -1421,7 +1421,7 @@ async def test_get_trigger_capabilities_value_updated_config_parameter_enumerate """Test we get the expected capabilities from an enumerated zwave_js.value_updated.config_parameter trigger.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device capabilities = await device_trigger.async_get_trigger_capabilities( @@ -1477,7 +1477,7 @@ async def test_failure_scenarios( dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, hank_binary_switch)} + identifiers={get_device_id(client.driver, hank_binary_switch)} ) assert device diff --git a/tests/components/zwave_js/test_diagnostics.py b/tests/components/zwave_js/test_diagnostics.py index aa5ec77b7981c0..4454e38e0d8c85 100644 --- a/tests/components/zwave_js/test_diagnostics.py +++ b/tests/components/zwave_js/test_diagnostics.py @@ -58,7 +58,9 @@ async def test_device_diagnostics( ) -> None: """Test the device level diagnostics data dump.""" dev_reg = dr.async_get(hass) - device = dev_reg.async_get_device({get_device_id(client.driver, multisensor_6)}) + device = dev_reg.async_get_device( + identifiers={get_device_id(client.driver, multisensor_6)} + ) assert device # Create mock config entry for fake entity @@ -151,7 +153,9 @@ async def test_device_diagnostics_missing_primary_value( ) -> None: """Test that device diagnostics handles an entity with a missing primary value.""" dev_reg = dr.async_get(hass) - device = dev_reg.async_get_device({get_device_id(client.driver, multisensor_6)}) + device = dev_reg.async_get_device( + identifiers={get_device_id(client.driver, multisensor_6)} + ) assert device entity_id = "sensor.multisensor_6_air_temperature" @@ -240,7 +244,7 @@ def _find_ultraviolet_val(data: dict) -> dict: client.driver.controller.emit("node added", {"node": node}) await hass.async_block_till_done() dev_reg = dr.async_get(hass) - device = dev_reg.async_get_device({get_device_id(client.driver, node)}) + device = dev_reg.async_get_device(identifiers={get_device_id(client.driver, node)}) assert device diagnostics_data = await get_diagnostics_for_device( diff --git a/tests/components/zwave_js/test_init.py b/tests/components/zwave_js/test_init.py index a33ee75661ca8b..3ec1f113b3e086 100644 --- a/tests/components/zwave_js/test_init.py +++ b/tests/components/zwave_js/test_init.py @@ -976,7 +976,9 @@ async def test_removed_device( assert len(device_entries) == 2 entity_entries = er.async_entries_for_config_entry(ent_reg, integration.entry_id) assert len(entity_entries) == 60 - assert dev_reg.async_get_device({get_device_id(driver, old_node)}) is None + assert ( + dev_reg.async_get_device(identifiers={get_device_id(driver, old_node)}) is None + ) async def test_suggested_area(hass: HomeAssistant, client, eaton_rf9640_dimmer) -> None: diff --git a/tests/components/zwave_js/test_services.py b/tests/components/zwave_js/test_services.py index a8671edbe64e2d..54638358fe7d1c 100644 --- a/tests/components/zwave_js/test_services.py +++ b/tests/components/zwave_js/test_services.py @@ -410,7 +410,9 @@ async def test_bulk_set_config_parameters( ) -> None: """Test the bulk_set_partial_config_parameters service.""" dev_reg = async_get_dev_reg(hass) - device = dev_reg.async_get_device({get_device_id(client.driver, multisensor_6)}) + device = dev_reg.async_get_device( + identifiers={get_device_id(client.driver, multisensor_6)} + ) assert device # Test setting config parameter by property and property_key await hass.services.async_call( @@ -757,7 +759,7 @@ async def test_set_value( """Test set_value service.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, climate_danfoss_lc_13)} + identifiers={get_device_id(client.driver, climate_danfoss_lc_13)} ) assert device @@ -1103,11 +1105,11 @@ async def test_multicast_set_value( # Test using area ID dev_reg = async_get_dev_reg(hass) device_eurotronic = dev_reg.async_get_device( - {get_device_id(client.driver, climate_eurotronic_spirit_z)} + identifiers={get_device_id(client.driver, climate_eurotronic_spirit_z)} ) assert device_eurotronic device_danfoss = dev_reg.async_get_device( - {get_device_id(client.driver, climate_danfoss_lc_13)} + identifiers={get_device_id(client.driver, climate_danfoss_lc_13)} ) assert device_danfoss area_reg = async_get_area_reg(hass) @@ -1416,7 +1418,7 @@ async def test_ping( """Test ping service.""" dev_reg = async_get_dev_reg(hass) device_radio_thermostat = dev_reg.async_get_device( - { + identifiers={ get_device_id( client.driver, climate_radio_thermostat_ct100_plus_different_endpoints ) @@ -1424,7 +1426,7 @@ async def test_ping( ) assert device_radio_thermostat device_danfoss = dev_reg.async_get_device( - {get_device_id(client.driver, climate_danfoss_lc_13)} + identifiers={get_device_id(client.driver, climate_danfoss_lc_13)} ) assert device_danfoss @@ -1566,7 +1568,7 @@ async def test_invoke_cc_api( """Test invoke_cc_api service.""" dev_reg = async_get_dev_reg(hass) device_radio_thermostat = dev_reg.async_get_device( - { + identifiers={ get_device_id( client.driver, climate_radio_thermostat_ct100_plus_different_endpoints ) @@ -1574,7 +1576,7 @@ async def test_invoke_cc_api( ) assert device_radio_thermostat device_danfoss = dev_reg.async_get_device( - {get_device_id(client.driver, climate_danfoss_lc_13)} + identifiers={get_device_id(client.driver, climate_danfoss_lc_13)} ) assert device_danfoss diff --git a/tests/components/zwave_js/test_trigger.py b/tests/components/zwave_js/test_trigger.py index eae9d6f5416fd0..501ad13cbaa4db 100644 --- a/tests/components/zwave_js/test_trigger.py +++ b/tests/components/zwave_js/test_trigger.py @@ -35,7 +35,7 @@ async def test_zwave_js_value_updated( node: Node = lock_schlage_be469 dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device @@ -459,7 +459,7 @@ async def test_zwave_js_event( node: Node = lock_schlage_be469 dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device @@ -1013,7 +1013,7 @@ async def test_zwave_js_trigger_config_entry_unloaded( """Test zwave_js triggers bypass dynamic validation when needed.""" dev_reg = async_get_dev_reg(hass) device = dev_reg.async_get_device( - {get_device_id(client.driver, lock_schlage_be469)} + identifiers={get_device_id(client.driver, lock_schlage_be469)} ) assert device diff --git a/tests/components/zwave_me/test_remove_stale_devices.py b/tests/components/zwave_me/test_remove_stale_devices.py index dca28929b3ba7d..d5496255addb16 100644 --- a/tests/components/zwave_me/test_remove_stale_devices.py +++ b/tests/components/zwave_me/test_remove_stale_devices.py @@ -60,7 +60,7 @@ async def test_remove_stale_devices( assert ( bool( device_registry.async_get_device( - { + identifiers={ ( "zwave_me", f"{config_entry.unique_id}-{identifier}", diff --git a/tests/helpers/test_device_registry.py b/tests/helpers/test_device_registry.py index e183bd4c38047f..7df5859f502853 100644 --- a/tests/helpers/test_device_registry.py +++ b/tests/helpers/test_device_registry.py @@ -530,8 +530,10 @@ async def test_removing_config_entries( assert entry2.config_entries == {"123", "456"} device_registry.async_clear_config_entry("123") - entry = device_registry.async_get_device({("bridgeid", "0123")}) - entry3_removed = device_registry.async_get_device({("bridgeid", "4567")}) + entry = device_registry.async_get_device(identifiers={("bridgeid", "0123")}) + entry3_removed = device_registry.async_get_device( + identifiers={("bridgeid", "4567")} + ) assert entry.config_entries == {"456"} assert entry3_removed is None @@ -664,7 +666,7 @@ async def test_removing_area_id(device_registry: dr.DeviceRegistry) -> None: entry_w_area = device_registry.async_update_device(entry.id, area_id="12345A") device_registry.async_clear_area_id("12345A") - entry_wo_area = device_registry.async_get_device({("bridgeid", "0123")}) + entry_wo_area = device_registry.async_get_device(identifiers={("bridgeid", "0123")}) assert not entry_wo_area.area_id assert entry_w_area != entry_wo_area @@ -692,7 +694,7 @@ async def test_specifying_via_device_create(device_registry: dr.DeviceRegistry) assert light.via_device_id == via.id device_registry.async_remove_device(via.id) - light = device_registry.async_get_device({("hue", "456")}) + light = device_registry.async_get_device(identifiers={("hue", "456")}) assert light.via_device_id is None @@ -821,9 +823,9 @@ async def test_loading_saving_data( assert list(device_registry.devices) == list(registry2.devices) assert list(device_registry.deleted_devices) == list(registry2.deleted_devices) - new_via = registry2.async_get_device({("hue", "0123")}) - new_light = registry2.async_get_device({("hue", "456")}) - new_light4 = registry2.async_get_device({("hue", "abc")}) + new_via = registry2.async_get_device(identifiers={("hue", "0123")}) + new_light = registry2.async_get_device(identifiers={("hue", "456")}) + new_light4 = registry2.async_get_device(identifiers={("hue", "abc")}) assert orig_via == new_via assert orig_light == new_light @@ -839,7 +841,7 @@ async def test_loading_saving_data( assert old.entry_type is new.entry_type # Ensure a save/load cycle does not keep suggested area - new_kitchen_light = registry2.async_get_device({("hue", "999")}) + new_kitchen_light = registry2.async_get_device(identifiers={("hue", "999")}) assert orig_kitchen_light.suggested_area == "Kitchen" orig_kitchen_light_witout_suggested_area = device_registry.async_update_device( @@ -951,15 +953,19 @@ async def test_update( via_device_id="98765B", ) - assert device_registry.async_get_device({("hue", "456")}) is None - assert device_registry.async_get_device({("bla", "123")}) is None + assert device_registry.async_get_device(identifiers={("hue", "456")}) is None + assert device_registry.async_get_device(identifiers={("bla", "123")}) is None - assert device_registry.async_get_device({("hue", "654")}) == updated_entry - assert device_registry.async_get_device({("bla", "321")}) == updated_entry + assert ( + device_registry.async_get_device(identifiers={("hue", "654")}) == updated_entry + ) + assert ( + device_registry.async_get_device(identifiers={("bla", "321")}) == updated_entry + ) assert ( device_registry.async_get_device( - {}, {(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")} + connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")} ) == updated_entry ) @@ -1032,7 +1038,7 @@ async def test_update_remove_config_entries( assert updated_entry.config_entries == {"456"} assert removed_entry is None - removed_entry = device_registry.async_get_device({("bridgeid", "4567")}) + removed_entry = device_registry.async_get_device(identifiers={("bridgeid", "4567")}) assert removed_entry is None @@ -1137,10 +1143,10 @@ async def test_cleanup_device_registry( dr.async_cleanup(hass, device_registry, ent_reg) - assert device_registry.async_get_device({("hue", "d1")}) is not None - assert device_registry.async_get_device({("hue", "d2")}) is not None - assert device_registry.async_get_device({("hue", "d3")}) is not None - assert device_registry.async_get_device({("something", "d4")}) is None + assert device_registry.async_get_device(identifiers={("hue", "d1")}) is not None + assert device_registry.async_get_device(identifiers={("hue", "d2")}) is not None + assert device_registry.async_get_device(identifiers={("hue", "d3")}) is not None + assert device_registry.async_get_device(identifiers={("something", "d4")}) is None async def test_cleanup_device_registry_removes_expired_orphaned_devices( diff --git a/tests/helpers/test_entity_platform.py b/tests/helpers/test_entity_platform.py index 9673e1dc73a7fb..e07c3cb475392d 100644 --- a/tests/helpers/test_entity_platform.py +++ b/tests/helpers/test_entity_platform.py @@ -1108,7 +1108,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities): assert len(hass.states.async_entity_ids()) == 2 - device = registry.async_get_device({("hue", "1234")}) + device = registry.async_get_device(identifiers={("hue", "1234")}) assert device is not None assert device.identifiers == {("hue", "1234")} assert device.configuration_url == "http://192.168.0.100/config" @@ -1162,7 +1162,9 @@ async def async_setup_entry(hass, config_entry, async_add_entities): assert await entity_platform.async_setup_entry(config_entry) await hass.async_block_till_done() - device2 = registry.async_get_device(set(), {(dr.CONNECTION_NETWORK_MAC, "abcd")}) + device2 = registry.async_get_device( + connections={(dr.CONNECTION_NETWORK_MAC, "abcd")} + ) assert device2 is not None assert device.id == device2.id assert device2.manufacturer == "test-manufacturer" @@ -1209,7 +1211,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities): assert len(hass.states.async_entity_ids()) == 1 - device = registry.async_get_device({("mqtt", "1234")}) + device = registry.async_get_device(identifiers={("mqtt", "1234")}) assert device is not None assert device.identifiers == {("mqtt", "1234")} assert device.configuration_url == "homeassistant://config/mqtt" @@ -1256,7 +1258,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities): assert len(hass.states.async_entity_ids()) == 1 - device = registry.async_get_device({("mqtt", "1234")}) + device = registry.async_get_device(identifiers={("mqtt", "1234")}) assert device is not None assert device.identifiers == {("mqtt", "1234")} assert device.configuration_url is None @@ -1836,7 +1838,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities): await hass.async_block_till_done() dev_reg = dr.async_get(hass) - device = dev_reg.async_get_device(set(), {(dr.CONNECTION_NETWORK_MAC, "1234")}) + device = dev_reg.async_get_device(connections={(dr.CONNECTION_NETWORK_MAC, "1234")}) assert device is not None assert device.name == expected_device_name From 3b80deb2b74d642e805f6b1abaa8c4be9253439e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20L=C3=B6vdahl?= Date: Thu, 13 Jul 2023 21:42:30 +0300 Subject: [PATCH 137/154] Fix Vallox fan entity naming (#96494) --- homeassistant/components/vallox/fan.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/vallox/fan.py b/homeassistant/components/vallox/fan.py index 34eee94411470d..b43dabbba80858 100644 --- a/homeassistant/components/vallox/fan.py +++ b/homeassistant/components/vallox/fan.py @@ -84,6 +84,7 @@ class ValloxFanEntity(ValloxEntity, FanEntity): """Representation of the fan.""" _attr_has_entity_name = True + _attr_name = None _attr_supported_features = FanEntityFeature.PRESET_MODE | FanEntityFeature.SET_SPEED def __init__( From da9624de2facf3770621676c68614876cb589d77 Mon Sep 17 00:00:00 2001 From: Oliver <10700296+ol-iver@users.noreply.github.com> Date: Thu, 13 Jul 2023 21:30:18 +0200 Subject: [PATCH 138/154] Update denonavr to `0.11.3` (#96467) --- homeassistant/components/denonavr/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/denonavr/manifest.json b/homeassistant/components/denonavr/manifest.json index 660e4c770b0cf5..b3c36ed39d2b84 100644 --- a/homeassistant/components/denonavr/manifest.json +++ b/homeassistant/components/denonavr/manifest.json @@ -6,7 +6,7 @@ "documentation": "https://www.home-assistant.io/integrations/denonavr", "iot_class": "local_push", "loggers": ["denonavr"], - "requirements": ["denonavr==0.11.2"], + "requirements": ["denonavr==0.11.3"], "ssdp": [ { "manufacturer": "Denon", diff --git a/requirements_all.txt b/requirements_all.txt index 103bcb889ef6b7..76ab11172bb09c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -649,7 +649,7 @@ deluge-client==1.7.1 demetriek==0.4.0 # homeassistant.components.denonavr -denonavr==0.11.2 +denonavr==0.11.3 # homeassistant.components.devolo_home_control devolo-home-control-api==0.18.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 114e164481c3f5..37388bfca95429 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -526,7 +526,7 @@ deluge-client==1.7.1 demetriek==0.4.0 # homeassistant.components.denonavr -denonavr==0.11.2 +denonavr==0.11.3 # homeassistant.components.devolo_home_control devolo-home-control-api==0.18.2 From 1865cd0805f9ddac19c692af283429b2902d64f6 Mon Sep 17 00:00:00 2001 From: Christopher Bailey Date: Thu, 13 Jul 2023 15:30:55 -0400 Subject: [PATCH 139/154] Bump unifiprotect to 4.10.5 (#96486) --- homeassistant/components/unifiprotect/camera.py | 2 +- homeassistant/components/unifiprotect/data.py | 2 +- homeassistant/components/unifiprotect/entity.py | 4 ++-- homeassistant/components/unifiprotect/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/unifiprotect/camera.py b/homeassistant/components/unifiprotect/camera.py index a4da77fe50b37d..019ff7b786363c 100644 --- a/homeassistant/components/unifiprotect/camera.py +++ b/homeassistant/components/unifiprotect/camera.py @@ -115,7 +115,7 @@ async def async_setup_entry( async def _add_new_device(device: ProtectAdoptableDeviceModel) -> None: if not isinstance(device, UFPCamera): - return + return # type: ignore[unreachable] entities = _async_camera_entities(data, ufp_device=device) async_add_entities(entities) diff --git a/homeassistant/components/unifiprotect/data.py b/homeassistant/components/unifiprotect/data.py index 3e4410fa41ad1e..73d05f1be1d77f 100644 --- a/homeassistant/components/unifiprotect/data.py +++ b/homeassistant/components/unifiprotect/data.py @@ -227,7 +227,7 @@ def _async_process_ws_message(self, message: WSSubscriptionMessage) -> None: self._async_update_device(obj, message.changed_data) # trigger updates for camera that the event references - elif isinstance(obj, Event): + elif isinstance(obj, Event): # type: ignore[unreachable] if obj.type in SMART_EVENTS: if obj.camera is not None: if obj.end is None: diff --git a/homeassistant/components/unifiprotect/entity.py b/homeassistant/components/unifiprotect/entity.py index 15bd17554ad30f..79ee483dd8d4f8 100644 --- a/homeassistant/components/unifiprotect/entity.py +++ b/homeassistant/components/unifiprotect/entity.py @@ -272,7 +272,7 @@ class ProtectNVREntity(ProtectDeviceEntity): """Base class for unifi protect entities.""" # separate subclass on purpose - device: NVR # type: ignore[assignment] + device: NVR def __init__( self, @@ -281,7 +281,7 @@ def __init__( description: EntityDescription | None = None, ) -> None: """Initialize the entity.""" - super().__init__(entry, device, description) # type: ignore[arg-type] + super().__init__(entry, device, description) @callback def _async_set_device_info(self) -> None: diff --git a/homeassistant/components/unifiprotect/manifest.json b/homeassistant/components/unifiprotect/manifest.json index cfa90664f36c02..95353e84754935 100644 --- a/homeassistant/components/unifiprotect/manifest.json +++ b/homeassistant/components/unifiprotect/manifest.json @@ -41,7 +41,7 @@ "iot_class": "local_push", "loggers": ["pyunifiprotect", "unifi_discovery"], "quality_scale": "platinum", - "requirements": ["pyunifiprotect==4.10.3", "unifi-discovery==1.1.7"], + "requirements": ["pyunifiprotect==4.10.5", "unifi-discovery==1.1.7"], "ssdp": [ { "manufacturer": "Ubiquiti Networks", diff --git a/requirements_all.txt b/requirements_all.txt index 76ab11172bb09c..59a058352f2442 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2186,7 +2186,7 @@ pytrafikverket==0.3.3 pyudev==0.23.2 # homeassistant.components.unifiprotect -pyunifiprotect==4.10.3 +pyunifiprotect==4.10.5 # homeassistant.components.uptimerobot pyuptimerobot==22.2.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 37388bfca95429..d3163bc5fd28a0 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1603,7 +1603,7 @@ pytrafikverket==0.3.3 pyudev==0.23.2 # homeassistant.components.unifiprotect -pyunifiprotect==4.10.3 +pyunifiprotect==4.10.5 # homeassistant.components.uptimerobot pyuptimerobot==22.2.0 From bfd4446d2e72da2c7c124d501045bd4668284bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20L=C3=B6vdahl?= Date: Fri, 14 Jul 2023 00:36:26 +0300 Subject: [PATCH 140/154] Bump vallox-websocket-api to 3.3.0 (#96493) --- homeassistant/components/vallox/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/vallox/manifest.json b/homeassistant/components/vallox/manifest.json index 4f3fcbf9c87601..479c84d238cfb4 100644 --- a/homeassistant/components/vallox/manifest.json +++ b/homeassistant/components/vallox/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/vallox", "iot_class": "local_polling", "loggers": ["vallox_websocket_api"], - "requirements": ["vallox-websocket-api==3.2.1"] + "requirements": ["vallox-websocket-api==3.3.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index 59a058352f2442..a1d3f619fd7858 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2602,7 +2602,7 @@ url-normalize==1.4.3 uvcclient==0.11.0 # homeassistant.components.vallox -vallox-websocket-api==3.2.1 +vallox-websocket-api==3.3.0 # homeassistant.components.rdw vehicle==1.0.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index d3163bc5fd28a0..b166ed3ae481a2 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1902,7 +1902,7 @@ url-normalize==1.4.3 uvcclient==0.11.0 # homeassistant.components.vallox -vallox-websocket-api==3.2.1 +vallox-websocket-api==3.3.0 # homeassistant.components.rdw vehicle==1.0.1 From c86b60bdf7ccb739c93951d4fbcabc4e3359824d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 13 Jul 2023 11:42:11 -1000 Subject: [PATCH 141/154] Bump bluetooth-data-tools to 1.6.0 (#96461) --- homeassistant/components/bluetooth/manifest.json | 2 +- homeassistant/components/esphome/manifest.json | 2 +- homeassistant/components/ld2410_ble/manifest.json | 2 +- homeassistant/components/led_ble/manifest.json | 2 +- homeassistant/package_constraints.txt | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/bluetooth/manifest.json b/homeassistant/components/bluetooth/manifest.json index bed677ebd306f0..f4c690dcffc556 100644 --- a/homeassistant/components/bluetooth/manifest.json +++ b/homeassistant/components/bluetooth/manifest.json @@ -18,7 +18,7 @@ "bleak-retry-connector==3.0.2", "bluetooth-adapters==0.16.0", "bluetooth-auto-recovery==1.2.1", - "bluetooth-data-tools==1.3.0", + "bluetooth-data-tools==1.6.0", "dbus-fast==1.86.0" ] } diff --git a/homeassistant/components/esphome/manifest.json b/homeassistant/components/esphome/manifest.json index 764b12cedc2438..4f208ed011541f 100644 --- a/homeassistant/components/esphome/manifest.json +++ b/homeassistant/components/esphome/manifest.json @@ -16,7 +16,7 @@ "loggers": ["aioesphomeapi", "noiseprotocol"], "requirements": [ "aioesphomeapi==15.1.6", - "bluetooth-data-tools==1.3.0", + "bluetooth-data-tools==1.6.0", "esphome-dashboard-api==1.2.3" ], "zeroconf": ["_esphomelib._tcp.local."] diff --git a/homeassistant/components/ld2410_ble/manifest.json b/homeassistant/components/ld2410_ble/manifest.json index 6eaf2885d89306..a161c3ecde1915 100644 --- a/homeassistant/components/ld2410_ble/manifest.json +++ b/homeassistant/components/ld2410_ble/manifest.json @@ -20,5 +20,5 @@ "documentation": "https://www.home-assistant.io/integrations/ld2410_ble/", "integration_type": "device", "iot_class": "local_push", - "requirements": ["bluetooth-data-tools==1.3.0", "ld2410-ble==0.1.1"] + "requirements": ["bluetooth-data-tools==1.6.0", "ld2410-ble==0.1.1"] } diff --git a/homeassistant/components/led_ble/manifest.json b/homeassistant/components/led_ble/manifest.json index cdc270f2e99371..51acbe8c7d9e5b 100644 --- a/homeassistant/components/led_ble/manifest.json +++ b/homeassistant/components/led_ble/manifest.json @@ -32,5 +32,5 @@ "dependencies": ["bluetooth_adapters"], "documentation": "https://www.home-assistant.io/integrations/led_ble/", "iot_class": "local_polling", - "requirements": ["bluetooth-data-tools==1.3.0", "led-ble==1.0.0"] + "requirements": ["bluetooth-data-tools==1.6.0", "led-ble==1.0.0"] } diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 8ae3ba06985ba3..6b3e1d8506df63 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -12,7 +12,7 @@ bleak-retry-connector==3.0.2 bleak==0.20.2 bluetooth-adapters==0.16.0 bluetooth-auto-recovery==1.2.1 -bluetooth-data-tools==1.3.0 +bluetooth-data-tools==1.6.0 certifi>=2021.5.30 ciso8601==2.3.0 cryptography==41.0.1 diff --git a/requirements_all.txt b/requirements_all.txt index a1d3f619fd7858..8742fd97c778f3 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -534,7 +534,7 @@ bluetooth-auto-recovery==1.2.1 # homeassistant.components.esphome # homeassistant.components.ld2410_ble # homeassistant.components.led_ble -bluetooth-data-tools==1.3.0 +bluetooth-data-tools==1.6.0 # homeassistant.components.bond bond-async==0.1.23 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index b166ed3ae481a2..f9237251ebaf79 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -448,7 +448,7 @@ bluetooth-auto-recovery==1.2.1 # homeassistant.components.esphome # homeassistant.components.ld2410_ble # homeassistant.components.led_ble -bluetooth-data-tools==1.3.0 +bluetooth-data-tools==1.6.0 # homeassistant.components.bond bond-async==0.1.23 From d2991d3f5e52e075b7064c7993a12cf98b2ed902 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 13 Jul 2023 13:20:24 -1000 Subject: [PATCH 142/154] Bump bond-async to 0.2.1 (#96504) --- homeassistant/components/bond/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/bond/manifest.json b/homeassistant/components/bond/manifest.json index fc91f8eb72efa8..08e4fb007b7ee6 100644 --- a/homeassistant/components/bond/manifest.json +++ b/homeassistant/components/bond/manifest.json @@ -7,6 +7,6 @@ "iot_class": "local_push", "loggers": ["bond_async"], "quality_scale": "platinum", - "requirements": ["bond-async==0.1.23"], + "requirements": ["bond-async==0.2.1"], "zeroconf": ["_bond._tcp.local."] } diff --git a/requirements_all.txt b/requirements_all.txt index 8742fd97c778f3..aa80f7676ca52c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -537,7 +537,7 @@ bluetooth-auto-recovery==1.2.1 bluetooth-data-tools==1.6.0 # homeassistant.components.bond -bond-async==0.1.23 +bond-async==0.2.1 # homeassistant.components.bosch_shc boschshcpy==0.2.57 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index f9237251ebaf79..0a7fe75fe45a46 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -451,7 +451,7 @@ bluetooth-auto-recovery==1.2.1 bluetooth-data-tools==1.6.0 # homeassistant.components.bond -bond-async==0.1.23 +bond-async==0.2.1 # homeassistant.components.bosch_shc boschshcpy==0.2.57 From 09237e4eff0d39ba7d1b7d8b228a6908c2317f0f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 13 Jul 2023 13:38:15 -1000 Subject: [PATCH 143/154] Remove unused code in ESPHome (#96503) --- homeassistant/components/esphome/domain_data.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/homeassistant/components/esphome/domain_data.py b/homeassistant/components/esphome/domain_data.py index 2fc32129d1f998..aacda1083985f1 100644 --- a/homeassistant/components/esphome/domain_data.py +++ b/homeassistant/components/esphome/domain_data.py @@ -78,10 +78,6 @@ def pop_entry_data(self, entry: ConfigEntry) -> RuntimeEntryData: """Pop the runtime entry data instance associated with this config entry.""" return self._entry_datas.pop(entry.entry_id) - def is_entry_loaded(self, entry: ConfigEntry) -> bool: - """Check whether the given entry is loaded.""" - return entry.entry_id in self._entry_datas - def get_or_create_store( self, hass: HomeAssistant, entry: ConfigEntry ) -> ESPHomeStorage: From bbc420bc9013403fb97dee800a3b8811ef1d7750 Mon Sep 17 00:00:00 2001 From: tronikos Date: Thu, 13 Jul 2023 17:52:26 -0700 Subject: [PATCH 144/154] Bump opower to 0.0.14 (#96506) --- homeassistant/components/opower/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/opower/manifest.json b/homeassistant/components/opower/manifest.json index 3b48e96a35194c..e7ebb7b546b0ba 100644 --- a/homeassistant/components/opower/manifest.json +++ b/homeassistant/components/opower/manifest.json @@ -6,5 +6,5 @@ "dependencies": ["recorder"], "documentation": "https://www.home-assistant.io/integrations/opower", "iot_class": "cloud_polling", - "requirements": ["opower==0.0.12"] + "requirements": ["opower==0.0.14"] } diff --git a/requirements_all.txt b/requirements_all.txt index aa80f7676ca52c..7497521708ae69 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1363,7 +1363,7 @@ openwrt-luci-rpc==1.1.16 openwrt-ubus-rpc==0.0.2 # homeassistant.components.opower -opower==0.0.12 +opower==0.0.14 # homeassistant.components.oralb oralb-ble==0.17.6 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 0a7fe75fe45a46..681c17952e4106 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1032,7 +1032,7 @@ openerz-api==0.2.0 openhomedevice==2.2.0 # homeassistant.components.opower -opower==0.0.12 +opower==0.0.14 # homeassistant.components.oralb oralb-ble==0.17.6 From c44c7bba840951509d9726588b76b009d64cdd0c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 13 Jul 2023 16:45:45 -1000 Subject: [PATCH 145/154] Simplify ESPHome bluetooth disconnected during operation wrapper (#96459) --- .../components/esphome/bluetooth/client.py | 52 ++++++++++--------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/homeassistant/components/esphome/bluetooth/client.py b/homeassistant/components/esphome/bluetooth/client.py index d452ab8764aef3..00b9883f26182f 100644 --- a/homeassistant/components/esphome/bluetooth/client.py +++ b/homeassistant/components/esphome/bluetooth/client.py @@ -62,29 +62,32 @@ def verify_connected(func: _WrapFuncType) -> _WrapFuncType: async def _async_wrap_bluetooth_connected_operation( self: ESPHomeClient, *args: Any, **kwargs: Any ) -> Any: - disconnected_event = ( - self._disconnected_event # pylint: disable=protected-access + loop = self._loop # pylint: disable=protected-access + disconnected_futures = ( + self._disconnected_futures # pylint: disable=protected-access ) - if not disconnected_event: - raise BleakError("Not connected") - action_task = asyncio.create_task(func(self, *args, **kwargs)) - disconnect_task = asyncio.create_task(disconnected_event.wait()) - await asyncio.wait( - (action_task, disconnect_task), - return_when=asyncio.FIRST_COMPLETED, - ) - if disconnect_task.done(): - action_task.cancel() - with contextlib.suppress(asyncio.CancelledError): - await action_task + disconnected_future = loop.create_future() + disconnected_futures.add(disconnected_future) + + task = asyncio.current_task(loop) + + def _on_disconnected(fut: asyncio.Future[None]) -> None: + if task and not task.done(): + task.cancel() + disconnected_future.add_done_callback(_on_disconnected) + try: + return await func(self, *args, **kwargs) + except asyncio.CancelledError as ex: + source_name = self._source_name # pylint: disable=protected-access + ble_device = self._ble_device # pylint: disable=protected-access raise BleakError( - f"{self._source_name}: " # pylint: disable=protected-access - f"{self._ble_device.name} - " # pylint: disable=protected-access - f" {self._ble_device.address}: " # pylint: disable=protected-access + f"{source_name}: {ble_device.name} - {ble_device.address}: " "Disconnected during operation" - ) - return action_task.result() + ) from ex + finally: + disconnected_futures.discard(disconnected_future) + disconnected_future.remove_done_callback(_on_disconnected) return cast(_WrapFuncType, _async_wrap_bluetooth_connected_operation) @@ -152,7 +155,8 @@ def __init__( self._notify_cancels: dict[ int, tuple[Callable[[], Coroutine[Any, Any, None]], Callable[[], None]] ] = {} - self._disconnected_event: asyncio.Event | None = None + self._loop = asyncio.get_running_loop() + self._disconnected_futures: set[asyncio.Future[None]] = set() device_info = self.entry_data.device_info assert device_info is not None self._device_info = device_info @@ -192,9 +196,10 @@ def _async_disconnected_cleanup(self) -> None: for _, notify_abort in self._notify_cancels.values(): notify_abort() self._notify_cancels.clear() - if self._disconnected_event: - self._disconnected_event.set() - self._disconnected_event = None + for future in self._disconnected_futures: + if not future.done(): + future.set_result(None) + self._disconnected_futures.clear() self._unsubscribe_connection_state() def _async_ble_device_disconnected(self) -> None: @@ -359,7 +364,6 @@ def _on_bluetooth_connection_state( await self.disconnect() raise - self._disconnected_event = asyncio.Event() return True @api_error_as_bleak_error From 0e8c85c5fc3d9c39930acd5b7fa69347688cc0ec Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 13 Jul 2023 16:46:09 -1000 Subject: [PATCH 146/154] Only lookup supported_features once in media_player capability_attributes (#96510) --- homeassistant/components/media_player/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/media_player/__init__.py b/homeassistant/components/media_player/__init__.py index 0f827d60736974..f9c68e2b1f01d7 100644 --- a/homeassistant/components/media_player/__init__.py +++ b/homeassistant/components/media_player/__init__.py @@ -1001,13 +1001,14 @@ def media_image_local(self) -> str | None: def capability_attributes(self) -> dict[str, Any]: """Return capability attributes.""" data: dict[str, Any] = {} + supported_features = self.supported_features - if self.supported_features & MediaPlayerEntityFeature.SELECT_SOURCE and ( + if supported_features & MediaPlayerEntityFeature.SELECT_SOURCE and ( source_list := self.source_list ): data[ATTR_INPUT_SOURCE_LIST] = source_list - if self.supported_features & MediaPlayerEntityFeature.SELECT_SOUND_MODE and ( + if supported_features & MediaPlayerEntityFeature.SELECT_SOUND_MODE and ( sound_mode_list := self.sound_mode_list ): data[ATTR_SOUND_MODE_LIST] = sound_mode_list From 3e429ae081a6d559bb397dcf99c4674431f79629 Mon Sep 17 00:00:00 2001 From: RenierM26 <66512715+RenierM26@users.noreply.github.com> Date: Fri, 14 Jul 2023 08:50:36 +0200 Subject: [PATCH 147/154] Add Ezviz last motion picture image entity (#94421) * Initial commit * Update camera.py * ignore type mismatch on append. * Use new image entity. * coveragerc update * Remove all changes to camera in this pull. * Fix docstring. * remove old "last_alarm_pic" sensor * Update image entity * bypass for content check error * Fix last updated not sting object * Remove redundant url change check. * Remove debug string * Check url change on coordinator data update. * Add translation key for name. * simplify update check * Rebase EzvizLastMotion ImageEntity * Change logging to debug. --- .coveragerc | 1 + homeassistant/components/ezviz/__init__.py | 1 + homeassistant/components/ezviz/image.py | 88 +++++++++++++++++++++ homeassistant/components/ezviz/sensor.py | 1 - homeassistant/components/ezviz/strings.json | 5 ++ 5 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 homeassistant/components/ezviz/image.py diff --git a/.coveragerc b/.coveragerc index 6b2870e84881af..52350a498d91d6 100644 --- a/.coveragerc +++ b/.coveragerc @@ -317,6 +317,7 @@ omit = homeassistant/components/ezviz/__init__.py homeassistant/components/ezviz/binary_sensor.py homeassistant/components/ezviz/camera.py + homeassistant/components/ezviz/image.py homeassistant/components/ezviz/light.py homeassistant/components/ezviz/coordinator.py homeassistant/components/ezviz/number.py diff --git a/homeassistant/components/ezviz/__init__.py b/homeassistant/components/ezviz/__init__.py index 9aeba56360e8d8..4355d3d2595cb3 100644 --- a/homeassistant/components/ezviz/__init__.py +++ b/homeassistant/components/ezviz/__init__.py @@ -35,6 +35,7 @@ ATTR_TYPE_CLOUD: [ Platform.BINARY_SENSOR, Platform.CAMERA, + Platform.IMAGE, Platform.LIGHT, Platform.NUMBER, Platform.SELECT, diff --git a/homeassistant/components/ezviz/image.py b/homeassistant/components/ezviz/image.py new file mode 100644 index 00000000000000..a5dbdea1d6f8ea --- /dev/null +++ b/homeassistant/components/ezviz/image.py @@ -0,0 +1,88 @@ +"""Support EZVIZ last motion image.""" +from __future__ import annotations + +import logging + +from homeassistant.components.image import Image, ImageEntity, ImageEntityDescription +from homeassistant.config_entries import ( + ConfigEntry, +) +from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers.entity_platform import ( + AddEntitiesCallback, +) +from homeassistant.util import dt as dt_util + +from .const import ( + DATA_COORDINATOR, + DOMAIN, +) +from .coordinator import EzvizDataUpdateCoordinator +from .entity import EzvizEntity + +_LOGGER = logging.getLogger(__name__) +GET_IMAGE_TIMEOUT = 10 + +IMAGE_TYPE = ImageEntityDescription( + key="last_motion_image", + translation_key="last_motion_image", +) + + +async def async_setup_entry( + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback +) -> None: + """Set up EZVIZ image entities based on a config entry.""" + + coordinator: EzvizDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id][ + DATA_COORDINATOR + ] + + async_add_entities( + EzvizLastMotion(hass, coordinator, camera) for camera in coordinator.data + ) + + +class EzvizLastMotion(EzvizEntity, ImageEntity): + """Return Last Motion Image from Ezviz Camera.""" + + _attr_has_entity_name = True + + def __init__( + self, hass: HomeAssistant, coordinator: EzvizDataUpdateCoordinator, serial: str + ) -> None: + """Initialize a image entity.""" + super().__init__(coordinator, serial) + ImageEntity.__init__(self, hass) + self._attr_unique_id = f"{serial}_{IMAGE_TYPE.key}" + self.entity_description = IMAGE_TYPE + self._attr_image_url = self.data["last_alarm_pic"] + self._attr_image_last_updated = dt_util.parse_datetime( + str(self.data["last_alarm_time"]) + ) + + async def _async_load_image_from_url(self, url: str) -> Image | None: + """Load an image by url.""" + if response := await self._fetch_url(url): + return Image( + content=response.content, + content_type="image/jpeg", # Actually returns binary/octet-stream + ) + return None + + @callback + def _handle_coordinator_update(self) -> None: + """Handle updated data from the coordinator.""" + if ( + self.data["last_alarm_pic"] + and self.data["last_alarm_pic"] != self._attr_image_url + ): + _LOGGER.debug("Image url changed to %s", self.data["last_alarm_pic"]) + + self._attr_image_url = self.data["last_alarm_pic"] + self._cached_image = None + self._attr_image_last_updated = dt_util.parse_datetime( + str(self.data["last_alarm_time"]) + ) + + super()._handle_coordinator_update() diff --git a/homeassistant/components/ezviz/sensor.py b/homeassistant/components/ezviz/sensor.py index 075fe6bd6d1b7d..1a8bfba21fb7a8 100644 --- a/homeassistant/components/ezviz/sensor.py +++ b/homeassistant/components/ezviz/sensor.py @@ -33,7 +33,6 @@ key="Seconds_Last_Trigger", entity_registry_enabled_default=False, ), - "last_alarm_pic": SensorEntityDescription(key="last_alarm_pic"), "supported_channels": SensorEntityDescription(key="supported_channels"), "local_ip": SensorEntityDescription(key="local_ip"), "wan_ip": SensorEntityDescription(key="wan_ip"), diff --git a/homeassistant/components/ezviz/strings.json b/homeassistant/components/ezviz/strings.json index aec1f892b1fbc2..1b244182059df3 100644 --- a/homeassistant/components/ezviz/strings.json +++ b/homeassistant/components/ezviz/strings.json @@ -93,6 +93,11 @@ "silent": "Silent" } } + }, + "image": { + "last_motion_image": { + "name": "Last motion image" + } } }, "services": { From 7a1f0a0b7410590108cb9bd04f80b5cc8a075a86 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 13 Jul 2023 22:37:59 -1000 Subject: [PATCH 148/154] Remove unneeded str() in StrEnum backport (#96509) --- homeassistant/backports/enum.py | 4 +++- homeassistant/components/demo/climate.py | 4 ++-- homeassistant/components/isy994/climate.py | 10 ++++++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/homeassistant/backports/enum.py b/homeassistant/backports/enum.py index 35562877bab34b..178859ecbe77dd 100644 --- a/homeassistant/backports/enum.py +++ b/homeassistant/backports/enum.py @@ -10,6 +10,8 @@ class StrEnum(str, Enum): """Partial backport of Python 3.11's StrEnum for our basic use cases.""" + value: str + def __new__(cls, value: str, *args: Any, **kwargs: Any) -> Self: """Create a new StrEnum instance.""" if not isinstance(value, str): @@ -18,7 +20,7 @@ def __new__(cls, value: str, *args: Any, **kwargs: Any) -> Self: def __str__(self) -> str: """Return self.value.""" - return str(self.value) + return self.value @staticmethod def _generate_next_value_( diff --git a/homeassistant/components/demo/climate.py b/homeassistant/components/demo/climate.py index 407860526ae797..bfc2cd1a2e71c3 100644 --- a/homeassistant/components/demo/climate.py +++ b/homeassistant/components/demo/climate.py @@ -64,7 +64,7 @@ async def async_setup_entry( aux=False, target_temp_high=None, target_temp_low=None, - hvac_modes=[cls.value for cls in HVACMode if cls != HVACMode.HEAT_COOL], + hvac_modes=[cls for cls in HVACMode if cls != HVACMode.HEAT_COOL], ), DemoClimate( unique_id="climate_3", @@ -83,7 +83,7 @@ async def async_setup_entry( aux=None, target_temp_high=24, target_temp_low=21, - hvac_modes=[cls.value for cls in HVACMode if cls != HVACMode.HEAT], + hvac_modes=[cls for cls in HVACMode if cls != HVACMode.HEAT], ), ] ) diff --git a/homeassistant/components/isy994/climate.py b/homeassistant/components/isy994/climate.py index 83fea57a9fa8a7..8fc90efaabcd98 100644 --- a/homeassistant/components/isy994/climate.py +++ b/homeassistant/components/isy994/climate.py @@ -37,6 +37,7 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.util.enum import try_parse_enum from .const import ( _LOGGER, @@ -131,7 +132,10 @@ def hvac_mode(self) -> HVACMode: if self._node.protocol == PROTO_INSTEON else UOM_HVAC_MODE_GENERIC ) - return UOM_TO_STATES[uom].get(hvac_mode.value, HVACMode.OFF) + return ( + try_parse_enum(HVACMode, UOM_TO_STATES[uom].get(hvac_mode.value)) + or HVACMode.OFF + ) @property def hvac_action(self) -> HVACAction | None: @@ -139,7 +143,9 @@ def hvac_action(self) -> HVACAction | None: hvac_action = self._node.aux_properties.get(PROP_HEAT_COOL_STATE) if not hvac_action: return None - return UOM_TO_STATES[UOM_HVAC_ACTIONS].get(hvac_action.value) + return try_parse_enum( + HVACAction, UOM_TO_STATES[UOM_HVAC_ACTIONS].get(hvac_action.value) + ) @property def current_temperature(self) -> float | None: From e44c74f9eb783e1ccea4598236b702496ca41453 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Jul 2023 11:52:24 +0200 Subject: [PATCH 149/154] Bump actions/setup-python from 4.6.1 to 4.7.0 (#96526) --- .github/workflows/builder.yml | 6 +++--- .github/workflows/ci.yaml | 24 ++++++++++++------------ .github/workflows/translations.yml | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml index 2ee32ca9dbc6e8..47e3e765b72789 100644 --- a/.github/workflows/builder.yml +++ b/.github/workflows/builder.yml @@ -29,7 +29,7 @@ jobs: fetch-depth: 0 - name: Set up Python ${{ env.DEFAULT_PYTHON }} - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 with: python-version: ${{ env.DEFAULT_PYTHON }} @@ -59,7 +59,7 @@ jobs: uses: actions/checkout@v3.5.3 - name: Set up Python ${{ env.DEFAULT_PYTHON }} - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 with: python-version: ${{ env.DEFAULT_PYTHON }} @@ -124,7 +124,7 @@ jobs: - name: Set up Python ${{ env.DEFAULT_PYTHON }} if: needs.init.outputs.channel == 'dev' - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 with: python-version: ${{ env.DEFAULT_PYTHON }} diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 368a3eb6e98c1b..89618685873036 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -209,7 +209,7 @@ jobs: uses: actions/checkout@v3.5.3 - name: Set up Python ${{ env.DEFAULT_PYTHON }} id: python - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 with: python-version: ${{ env.DEFAULT_PYTHON }} check-latest: true @@ -253,7 +253,7 @@ jobs: - name: Check out code from GitHub uses: actions/checkout@v3.5.3 - name: Set up Python ${{ env.DEFAULT_PYTHON }} - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 id: python with: python-version: ${{ env.DEFAULT_PYTHON }} @@ -299,7 +299,7 @@ jobs: - name: Check out code from GitHub uses: actions/checkout@v3.5.3 - name: Set up Python ${{ env.DEFAULT_PYTHON }} - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 id: python with: python-version: ${{ env.DEFAULT_PYTHON }} @@ -348,7 +348,7 @@ jobs: - name: Check out code from GitHub uses: actions/checkout@v3.5.3 - name: Set up Python ${{ env.DEFAULT_PYTHON }} - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 id: python with: python-version: ${{ env.DEFAULT_PYTHON }} @@ -443,7 +443,7 @@ jobs: uses: actions/checkout@v3.5.3 - name: Set up Python ${{ matrix.python-version }} id: python - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 with: python-version: ${{ matrix.python-version }} check-latest: true @@ -511,7 +511,7 @@ jobs: uses: actions/checkout@v3.5.3 - name: Set up Python ${{ env.DEFAULT_PYTHON }} id: python - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 with: python-version: ${{ env.DEFAULT_PYTHON }} check-latest: true @@ -543,7 +543,7 @@ jobs: uses: actions/checkout@v3.5.3 - name: Set up Python ${{ env.DEFAULT_PYTHON }} id: python - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 with: python-version: ${{ env.DEFAULT_PYTHON }} check-latest: true @@ -576,7 +576,7 @@ jobs: uses: actions/checkout@v3.5.3 - name: Set up Python ${{ env.DEFAULT_PYTHON }} id: python - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 with: python-version: ${{ env.DEFAULT_PYTHON }} check-latest: true @@ -620,7 +620,7 @@ jobs: uses: actions/checkout@v3.5.3 - name: Set up Python ${{ env.DEFAULT_PYTHON }} id: python - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 with: python-version: ${{ env.DEFAULT_PYTHON }} check-latest: true @@ -702,7 +702,7 @@ jobs: uses: actions/checkout@v3.5.3 - name: Set up Python ${{ matrix.python-version }} id: python - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 with: python-version: ${{ matrix.python-version }} check-latest: true @@ -827,7 +827,7 @@ jobs: uses: actions/checkout@v3.5.3 - name: Set up Python ${{ matrix.python-version }} id: python - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 with: python-version: ${{ matrix.python-version }} check-latest: true @@ -934,7 +934,7 @@ jobs: uses: actions/checkout@v3.5.3 - name: Set up Python ${{ matrix.python-version }} id: python - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 with: python-version: ${{ matrix.python-version }} check-latest: true diff --git a/.github/workflows/translations.yml b/.github/workflows/translations.yml index dd1f3d061a99f7..1d77ac8f13006f 100644 --- a/.github/workflows/translations.yml +++ b/.github/workflows/translations.yml @@ -22,7 +22,7 @@ jobs: uses: actions/checkout@v3.5.3 - name: Set up Python ${{ env.DEFAULT_PYTHON }} - uses: actions/setup-python@v4.6.1 + uses: actions/setup-python@v4.7.0 with: python-version: ${{ env.DEFAULT_PYTHON }} From 3b32dcb6133cdb767b9b677bfe0839e1a137d131 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Fri, 14 Jul 2023 12:28:19 +0200 Subject: [PATCH 150/154] Revert translation reference for Tuya motion_sensitivity (#96536) --- homeassistant/components/tuya/strings.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/tuya/strings.json b/homeassistant/components/tuya/strings.json index ccb7d878a4989f..e7896f5da8623d 100644 --- a/homeassistant/components/tuya/strings.json +++ b/homeassistant/components/tuya/strings.json @@ -61,9 +61,9 @@ }, "motion_sensitivity": { "state": { - "0": "[%key:component::tuya::entity::select::decibel_sensitivity::state::0%]", + "0": "Low sensitivity", "1": "Medium sensitivity", - "2": "[%key:component::tuya::entity::select::decibel_sensitivity::state::1%]" + "2": "High sensitivity" } }, "record_mode": { From 614f3c6a15713aa762269f7c628d4420987cbd4c Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Fri, 14 Jul 2023 14:55:17 +0200 Subject: [PATCH 151/154] Move device info validation to device registry (#96465) * Move device info validation to device registry * Don't move DeviceInfo * Fix type annotation * Don't block adding device for unknown config entry * Fix test * Remove use of locals() * Improve error message --- homeassistant/exceptions.py | 15 --- homeassistant/helpers/device_registry.py | 145 +++++++++++++++++++++-- homeassistant/helpers/entity_platform.py | 99 ++-------------- tests/helpers/test_device_registry.py | 24 ++-- tests/helpers/test_entity.py | 1 + tests/helpers/test_entity_platform.py | 1 + 6 files changed, 159 insertions(+), 126 deletions(-) diff --git a/homeassistant/exceptions.py b/homeassistant/exceptions.py index bfc96eabfdfbce..2946c8c3743481 100644 --- a/homeassistant/exceptions.py +++ b/homeassistant/exceptions.py @@ -191,21 +191,6 @@ def __init__(self, value: str, property_name: str, max_length: int) -> None: self.max_length = max_length -class RequiredParameterMissing(HomeAssistantError): - """Raised when a required parameter is missing from a function call.""" - - def __init__(self, parameter_names: list[str]) -> None: - """Initialize error.""" - super().__init__( - self, - ( - "Call must include at least one of the following parameters: " - f"{', '.join(parameter_names)}" - ), - ) - self.parameter_names = parameter_names - - class DependencyError(HomeAssistantError): """Raised when dependencies cannot be setup.""" diff --git a/homeassistant/helpers/device_registry.py b/homeassistant/helpers/device_registry.py index 79b4eac68d55ca..a59313ed8863cc 100644 --- a/homeassistant/helpers/device_registry.py +++ b/homeassistant/helpers/device_registry.py @@ -6,13 +6,14 @@ import logging import time from typing import TYPE_CHECKING, Any, TypeVar, cast +from urllib.parse import urlparse import attr from homeassistant.backports.enum import StrEnum from homeassistant.const import EVENT_HOMEASSISTANT_STARTED, EVENT_HOMEASSISTANT_STOP from homeassistant.core import Event, HomeAssistant, callback -from homeassistant.exceptions import HomeAssistantError, RequiredParameterMissing +from homeassistant.exceptions import HomeAssistantError from homeassistant.util.json import format_unserializable_data import homeassistant.util.uuid as uuid_util @@ -26,6 +27,7 @@ from homeassistant.config_entries import ConfigEntry from . import entity_registry + from .entity import DeviceInfo _LOGGER = logging.getLogger(__name__) @@ -60,6 +62,39 @@ class DeviceEntryDisabler(StrEnum): DISABLED_INTEGRATION = DeviceEntryDisabler.INTEGRATION.value DISABLED_USER = DeviceEntryDisabler.USER.value +DEVICE_INFO_TYPES = { + # Device info is categorized by finding the first device info type which has all + # the keys of the device info. The link device info type must be kept first + # to make it preferred over primary. + "link": { + "connections", + "identifiers", + }, + "primary": { + "configuration_url", + "connections", + "entry_type", + "hw_version", + "identifiers", + "manufacturer", + "model", + "name", + "suggested_area", + "sw_version", + "via_device", + }, + "secondary": { + "connections", + "default_manufacturer", + "default_model", + "default_name", + # Used by Fritz + "via_device", + }, +} + +DEVICE_INFO_KEYS = set.union(*(itm for itm in DEVICE_INFO_TYPES.values())) + class DeviceEntryType(StrEnum): """Device entry type.""" @@ -67,6 +102,66 @@ class DeviceEntryType(StrEnum): SERVICE = "service" +class DeviceInfoError(HomeAssistantError): + """Raised when device info is invalid.""" + + def __init__(self, domain: str, device_info: DeviceInfo, message: str) -> None: + """Initialize error.""" + super().__init__( + f"Invalid device info {device_info} for '{domain}' config entry: {message}", + ) + self.device_info = device_info + self.domain = domain + + +def _validate_device_info( + config_entry: ConfigEntry | None, + device_info: DeviceInfo, +) -> str: + """Process a device info.""" + keys = set(device_info) + + # If no keys or not enough info to match up, abort + if not device_info.get("connections") and not device_info.get("identifiers"): + raise DeviceInfoError( + config_entry.domain if config_entry else "unknown", + device_info, + "device info must include at least one of identifiers or connections", + ) + + device_info_type: str | None = None + + # Find the first device info type which has all keys in the device info + for possible_type, allowed_keys in DEVICE_INFO_TYPES.items(): + if keys <= allowed_keys: + device_info_type = possible_type + break + + if device_info_type is None: + raise DeviceInfoError( + config_entry.domain if config_entry else "unknown", + device_info, + ( + "device info needs to either describe a device, " + "link to existing device or provide extra information." + ), + ) + + if (config_url := device_info.get("configuration_url")) is not None: + if type(config_url) is not str or urlparse(config_url).scheme not in [ + "http", + "https", + "homeassistant", + ]: + raise DeviceInfoError( + config_entry.domain if config_entry else "unknown", + device_info, + f"invalid configuration_url '{config_url}'", + ) + + return device_info_type + + @attr.s(slots=True, frozen=True) class DeviceEntry: """Device Registry Entry.""" @@ -338,7 +433,7 @@ def async_get_or_create( *, config_entry_id: str, configuration_url: str | None | UndefinedType = UNDEFINED, - connections: set[tuple[str, str]] | None = None, + connections: set[tuple[str, str]] | None | UndefinedType = UNDEFINED, default_manufacturer: str | None | UndefinedType = UNDEFINED, default_model: str | None | UndefinedType = UNDEFINED, default_name: str | None | UndefinedType = UNDEFINED, @@ -346,22 +441,47 @@ def async_get_or_create( disabled_by: DeviceEntryDisabler | None | UndefinedType = UNDEFINED, entry_type: DeviceEntryType | None | UndefinedType = UNDEFINED, hw_version: str | None | UndefinedType = UNDEFINED, - identifiers: set[tuple[str, str]] | None = None, + identifiers: set[tuple[str, str]] | None | UndefinedType = UNDEFINED, manufacturer: str | None | UndefinedType = UNDEFINED, model: str | None | UndefinedType = UNDEFINED, name: str | None | UndefinedType = UNDEFINED, suggested_area: str | None | UndefinedType = UNDEFINED, sw_version: str | None | UndefinedType = UNDEFINED, - via_device: tuple[str, str] | None = None, + via_device: tuple[str, str] | None | UndefinedType = UNDEFINED, ) -> DeviceEntry: """Get device. Create if it doesn't exist.""" - if not identifiers and not connections: - raise RequiredParameterMissing(["identifiers", "connections"]) - if identifiers is None: + # Reconstruct a DeviceInfo dict from the arguments. + # When we upgrade to Python 3.12, we can change this method to instead + # accept kwargs typed as a DeviceInfo dict (PEP 692) + device_info: DeviceInfo = {} + for key, val in ( + ("configuration_url", configuration_url), + ("connections", connections), + ("default_manufacturer", default_manufacturer), + ("default_model", default_model), + ("default_name", default_name), + ("entry_type", entry_type), + ("hw_version", hw_version), + ("identifiers", identifiers), + ("manufacturer", manufacturer), + ("model", model), + ("name", name), + ("suggested_area", suggested_area), + ("sw_version", sw_version), + ("via_device", via_device), + ): + if val is UNDEFINED: + continue + device_info[key] = val # type: ignore[literal-required] + + config_entry = self.hass.config_entries.async_get_entry(config_entry_id) + device_info_type = _validate_device_info(config_entry, device_info) + + if identifiers is None or identifiers is UNDEFINED: identifiers = set() - if connections is None: + if connections is None or connections is UNDEFINED: connections = set() else: connections = _normalize_connections(connections) @@ -378,6 +498,13 @@ def async_get_or_create( config_entry_id, connections, identifiers ) self.devices[device.id] = device + # If creating a new device, default to the config entry name + if ( + device_info_type == "primary" + and (not name or name is UNDEFINED) + and config_entry + ): + name = config_entry.title if default_manufacturer is not UNDEFINED and device.manufacturer is None: manufacturer = default_manufacturer @@ -388,7 +515,7 @@ def async_get_or_create( if default_name is not UNDEFINED and device.name is None: name = default_name - if via_device is not None: + if via_device is not None and via_device is not UNDEFINED: via = self.async_get_device(identifiers={via_device}) via_device_id: str | UndefinedType = via.id if via else UNDEFINED else: diff --git a/homeassistant/helpers/entity_platform.py b/homeassistant/helpers/entity_platform.py index f97e509f486943..067d6430c9f8c6 100644 --- a/homeassistant/helpers/entity_platform.py +++ b/homeassistant/helpers/entity_platform.py @@ -7,7 +7,6 @@ from datetime import datetime, timedelta from logging import Logger, getLogger from typing import TYPE_CHECKING, Any, Protocol -from urllib.parse import urlparse import voluptuous as vol @@ -48,7 +47,7 @@ from .typing import UNDEFINED, ConfigType, DiscoveryInfoType if TYPE_CHECKING: - from .entity import DeviceInfo, Entity + from .entity import Entity SLOW_SETUP_WARNING = 10 @@ -60,37 +59,6 @@ DATA_ENTITY_PLATFORM = "entity_platform" PLATFORM_NOT_READY_BASE_WAIT_TIME = 30 # seconds -DEVICE_INFO_TYPES = { - # Device info is categorized by finding the first device info type which has all - # the keys of the device info. The link device info type must be kept first - # to make it preferred over primary. - "link": { - "connections", - "identifiers", - }, - "primary": { - "configuration_url", - "connections", - "entry_type", - "hw_version", - "identifiers", - "manufacturer", - "model", - "name", - "suggested_area", - "sw_version", - "via_device", - }, - "secondary": { - "connections", - "default_manufacturer", - "default_model", - "default_name", - # Used by Fritz - "via_device", - }, -} - _LOGGER = getLogger(__name__) @@ -646,7 +614,14 @@ async def _async_add_entity( # noqa: C901 return if self.config_entry and (device_info := entity.device_info): - device = self._async_process_device_info(device_info) + try: + device = dev_reg.async_get(self.hass).async_get_or_create( + config_entry_id=self.config_entry.entry_id, + **device_info, + ) + except dev_reg.DeviceInfoError as exc: + self.logger.error("Ignoring invalid device info: %s", str(exc)) + device = None else: device = None @@ -773,62 +748,6 @@ def remove_entity_cb() -> None: await entity.add_to_platform_finish() - @callback - def _async_process_device_info( - self, device_info: DeviceInfo - ) -> dev_reg.DeviceEntry | None: - """Process a device info.""" - keys = set(device_info) - - # If no keys or not enough info to match up, abort - if len(keys & {"connections", "identifiers"}) == 0: - self.logger.error( - "Ignoring device info without identifiers or connections: %s", - device_info, - ) - return None - - device_info_type: str | None = None - - # Find the first device info type which has all keys in the device info - for possible_type, allowed_keys in DEVICE_INFO_TYPES.items(): - if keys <= allowed_keys: - device_info_type = possible_type - break - - if device_info_type is None: - self.logger.error( - "Device info for %s needs to either describe a device, " - "link to existing device or provide extra information.", - device_info, - ) - return None - - if (config_url := device_info.get("configuration_url")) is not None: - if type(config_url) is not str or urlparse(config_url).scheme not in [ - "http", - "https", - "homeassistant", - ]: - self.logger.error( - "Ignoring device info with invalid configuration_url '%s'", - config_url, - ) - return None - - assert self.config_entry is not None - - if device_info_type == "primary" and not device_info.get("name"): - device_info = { - **device_info, # type: ignore[misc] - "name": self.config_entry.title, - } - - return dev_reg.async_get(self.hass).async_get_or_create( - config_entry_id=self.config_entry.entry_id, - **device_info, - ) - async def async_reset(self) -> None: """Remove all entities and reset data. diff --git a/tests/helpers/test_device_registry.py b/tests/helpers/test_device_registry.py index 7df5859f502853..3e59b08cfa8fff 100644 --- a/tests/helpers/test_device_registry.py +++ b/tests/helpers/test_device_registry.py @@ -8,7 +8,7 @@ from homeassistant import config_entries from homeassistant.const import EVENT_HOMEASSISTANT_STARTED from homeassistant.core import CoreState, HomeAssistant, callback -from homeassistant.exceptions import RequiredParameterMissing +from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import ( area_registry as ar, device_registry as dr, @@ -118,7 +118,7 @@ async def test_requirement_for_identifier_or_connection( assert entry assert entry2 - with pytest.raises(RequiredParameterMissing) as exc_info: + with pytest.raises(HomeAssistantError): device_registry.async_get_or_create( config_entry_id="1234", connections=set(), @@ -127,8 +127,6 @@ async def test_requirement_for_identifier_or_connection( model="model", ) - assert exc_info.value.parameter_names == ["identifiers", "connections"] - async def test_multiple_config_entries(device_registry: dr.DeviceRegistry) -> None: """Make sure we do not get duplicate entries.""" @@ -1462,7 +1460,8 @@ async def test_get_or_create_empty_then_set_default_values( ) -> None: """Test creating an entry, then setting default name, model, manufacturer.""" entry = device_registry.async_get_or_create( - identifiers={("bridgeid", "0123")}, config_entry_id="1234" + config_entry_id="1234", + connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) assert entry.name is None assert entry.model is None @@ -1470,7 +1469,7 @@ async def test_get_or_create_empty_then_set_default_values( entry = device_registry.async_get_or_create( config_entry_id="1234", - identifiers={("bridgeid", "0123")}, + connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, default_name="default name 1", default_model="default model 1", default_manufacturer="default manufacturer 1", @@ -1481,7 +1480,7 @@ async def test_get_or_create_empty_then_set_default_values( entry = device_registry.async_get_or_create( config_entry_id="1234", - identifiers={("bridgeid", "0123")}, + connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, default_name="default name 2", default_model="default model 2", default_manufacturer="default manufacturer 2", @@ -1496,7 +1495,8 @@ async def test_get_or_create_empty_then_update( ) -> None: """Test creating an entry, then setting name, model, manufacturer.""" entry = device_registry.async_get_or_create( - identifiers={("bridgeid", "0123")}, config_entry_id="1234" + config_entry_id="1234", + connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, ) assert entry.name is None assert entry.model is None @@ -1504,7 +1504,7 @@ async def test_get_or_create_empty_then_update( entry = device_registry.async_get_or_create( config_entry_id="1234", - identifiers={("bridgeid", "0123")}, + connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, name="name 1", model="model 1", manufacturer="manufacturer 1", @@ -1515,7 +1515,7 @@ async def test_get_or_create_empty_then_update( entry = device_registry.async_get_or_create( config_entry_id="1234", - identifiers={("bridgeid", "0123")}, + connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, default_name="default name 1", default_model="default model 1", default_manufacturer="default manufacturer 1", @@ -1531,7 +1531,7 @@ async def test_get_or_create_sets_default_values( """Test creating an entry, then setting default name, model, manufacturer.""" entry = device_registry.async_get_or_create( config_entry_id="1234", - identifiers={("bridgeid", "0123")}, + connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, default_name="default name 1", default_model="default model 1", default_manufacturer="default manufacturer 1", @@ -1542,7 +1542,7 @@ async def test_get_or_create_sets_default_values( entry = device_registry.async_get_or_create( config_entry_id="1234", - identifiers={("bridgeid", "0123")}, + connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, default_name="default name 2", default_model="default model 2", default_manufacturer="default manufacturer 2", diff --git a/tests/helpers/test_entity.py b/tests/helpers/test_entity.py index 7de6f70e793698..0d9ee76ac62e94 100644 --- a/tests/helpers/test_entity.py +++ b/tests/helpers/test_entity.py @@ -972,6 +972,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities): platform = MockPlatform(async_setup_entry=async_setup_entry) config_entry = MockConfigEntry(entry_id="super-mock-id") + config_entry.add_to_hass(hass) entity_platform = MockEntityPlatform( hass, platform_name=config_entry.domain, platform=platform ) diff --git a/tests/helpers/test_entity_platform.py b/tests/helpers/test_entity_platform.py index e07c3cb475392d..1f7e579ea95310 100644 --- a/tests/helpers/test_entity_platform.py +++ b/tests/helpers/test_entity_platform.py @@ -1830,6 +1830,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities): platform = MockPlatform(async_setup_entry=async_setup_entry) config_entry = MockConfigEntry(title=config_entry_title, entry_id="super-mock-id") + config_entry.add_to_hass(hass) entity_platform = MockEntityPlatform( hass, platform_name=config_entry.domain, platform=platform ) From afdded58eec01031f657a86865d61e0f767bfc54 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Fri, 14 Jul 2023 07:56:27 -0500 Subject: [PATCH 152/154] Wyoming Piper 1.1 (#96490) * Add voice/speaker options to Piper TTS * Use description if available * Fix tests * Clean up if --- homeassistant/components/wyoming/__init__.py | 7 +++- homeassistant/components/wyoming/const.py | 3 ++ .../components/wyoming/manifest.json | 2 +- homeassistant/components/wyoming/tts.py | 26 +++++++++++---- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/wyoming/__init__.py | 15 ++++++++- .../wyoming/snapshots/test_tts.ambr | 15 +++++++++ tests/components/wyoming/test_tts.py | 33 +++++++++++++++++-- 9 files changed, 92 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/wyoming/__init__.py b/homeassistant/components/wyoming/__init__.py index 8676365212accc..33064d21097554 100644 --- a/homeassistant/components/wyoming/__init__.py +++ b/homeassistant/components/wyoming/__init__.py @@ -7,11 +7,16 @@ from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryNotReady -from .const import DOMAIN +from .const import ATTR_SPEAKER, DOMAIN from .data import WyomingService _LOGGER = logging.getLogger(__name__) +__all__ = [ + "ATTR_SPEAKER", + "DOMAIN", +] + async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Load Wyoming.""" diff --git a/homeassistant/components/wyoming/const.py b/homeassistant/components/wyoming/const.py index 26443cc11eba2e..fd73a6bd047439 100644 --- a/homeassistant/components/wyoming/const.py +++ b/homeassistant/components/wyoming/const.py @@ -5,3 +5,6 @@ SAMPLE_RATE = 16000 SAMPLE_WIDTH = 2 SAMPLE_CHANNELS = 1 + +# For multi-speaker voices, this is the name of the selected speaker. +ATTR_SPEAKER = "speaker" diff --git a/homeassistant/components/wyoming/manifest.json b/homeassistant/components/wyoming/manifest.json index 9ad8092bb8c445..7fbf3542e13dbc 100644 --- a/homeassistant/components/wyoming/manifest.json +++ b/homeassistant/components/wyoming/manifest.json @@ -5,5 +5,5 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/wyoming", "iot_class": "local_push", - "requirements": ["wyoming==0.0.1"] + "requirements": ["wyoming==1.0.0"] } diff --git a/homeassistant/components/wyoming/tts.py b/homeassistant/components/wyoming/tts.py index 0fc7bf5e6c4cd0..6510fd8c761243 100644 --- a/homeassistant/components/wyoming/tts.py +++ b/homeassistant/components/wyoming/tts.py @@ -6,14 +6,14 @@ from wyoming.audio import AudioChunk, AudioChunkConverter, AudioStop from wyoming.client import AsyncTcpClient -from wyoming.tts import Synthesize +from wyoming.tts import Synthesize, SynthesizeVoice from homeassistant.components import tts from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddEntitiesCallback -from .const import DOMAIN +from .const import ATTR_SPEAKER, DOMAIN from .data import WyomingService from .error import WyomingError @@ -57,10 +57,16 @@ def __init__( self._voices[language].append( tts.Voice( voice_id=voice.name, - name=voice.name, + name=voice.description or voice.name, ) ) + # Sort voices by name + for language in self._voices: + self._voices[language] = sorted( + self._voices[language], key=lambda v: v.name + ) + self._supported_languages: list[str] = list(voice_languages) self._attr_name = self._tts_service.name @@ -82,7 +88,7 @@ def supported_languages(self): @property def supported_options(self): """Return list of supported options like voice, emotion.""" - return [tts.ATTR_AUDIO_OUTPUT, tts.ATTR_VOICE] + return [tts.ATTR_AUDIO_OUTPUT, tts.ATTR_VOICE, ATTR_SPEAKER] @property def default_options(self): @@ -95,10 +101,18 @@ def async_get_supported_voices(self, language: str) -> list[tts.Voice] | None: return self._voices.get(language) async def async_get_tts_audio(self, message, language, options): - """Load TTS from UNIX socket.""" + """Load TTS from TCP socket.""" + voice_name: str | None = options.get(tts.ATTR_VOICE) + voice_speaker: str | None = options.get(ATTR_SPEAKER) + try: async with AsyncTcpClient(self.service.host, self.service.port) as client: - await client.write_event(Synthesize(message).event()) + voice: SynthesizeVoice | None = None + if voice_name is not None: + voice = SynthesizeVoice(name=voice_name, speaker=voice_speaker) + + synthesize = Synthesize(text=message, voice=voice) + await client.write_event(synthesize.event()) with io.BytesIO() as wav_io: wav_writer: wave.Wave_write | None = None diff --git a/requirements_all.txt b/requirements_all.txt index 7497521708ae69..74c409bc8c1023 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2681,7 +2681,7 @@ wled==0.16.0 wolf-smartset==0.1.11 # homeassistant.components.wyoming -wyoming==0.0.1 +wyoming==1.0.0 # homeassistant.components.xbox xbox-webapi==2.0.11 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 681c17952e4106..24f5987227f739 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1963,7 +1963,7 @@ wled==0.16.0 wolf-smartset==0.1.11 # homeassistant.components.wyoming -wyoming==0.0.1 +wyoming==1.0.0 # homeassistant.components.xbox xbox-webapi==2.0.11 diff --git a/tests/components/wyoming/__init__.py b/tests/components/wyoming/__init__.py index d48b908f26b7e6..3d12d41ce5e273 100644 --- a/tests/components/wyoming/__init__.py +++ b/tests/components/wyoming/__init__.py @@ -1,16 +1,26 @@ """Tests for the Wyoming integration.""" -from wyoming.info import AsrModel, AsrProgram, Attribution, Info, TtsProgram, TtsVoice +from wyoming.info import ( + AsrModel, + AsrProgram, + Attribution, + Info, + TtsProgram, + TtsVoice, + TtsVoiceSpeaker, +) TEST_ATTR = Attribution(name="Test", url="http://www.test.com") STT_INFO = Info( asr=[ AsrProgram( name="Test ASR", + description="Test ASR", installed=True, attribution=TEST_ATTR, models=[ AsrModel( name="Test Model", + description="Test Model", installed=True, attribution=TEST_ATTR, languages=["en-US"], @@ -23,14 +33,17 @@ tts=[ TtsProgram( name="Test TTS", + description="Test TTS", installed=True, attribution=TEST_ATTR, voices=[ TtsVoice( name="Test Voice", + description="Test Voice", installed=True, attribution=TEST_ATTR, languages=["en-US"], + speakers=[TtsVoiceSpeaker(name="Test Speaker")], ) ], ) diff --git a/tests/components/wyoming/snapshots/test_tts.ambr b/tests/components/wyoming/snapshots/test_tts.ambr index eb0b33c3276fca..1cb5a6cb874ac8 100644 --- a/tests/components/wyoming/snapshots/test_tts.ambr +++ b/tests/components/wyoming/snapshots/test_tts.ambr @@ -21,3 +21,18 @@ }), ]) # --- +# name: test_voice_speaker + list([ + dict({ + 'data': dict({ + 'text': 'Hello world', + 'voice': dict({ + 'name': 'voice1', + 'speaker': 'speaker1', + }), + }), + 'payload': None, + 'type': 'synthesize', + }), + ]) +# --- diff --git a/tests/components/wyoming/test_tts.py b/tests/components/wyoming/test_tts.py index 8767660ca08795..51a684bc4fd13f 100644 --- a/tests/components/wyoming/test_tts.py +++ b/tests/components/wyoming/test_tts.py @@ -8,7 +8,7 @@ import pytest from wyoming.audio import AudioChunk, AudioStop -from homeassistant.components import tts +from homeassistant.components import tts, wyoming from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.entity_component import DATA_INSTANCES @@ -31,7 +31,11 @@ async def test_support(hass: HomeAssistant, init_wyoming_tts) -> None: assert entity is not None assert entity.supported_languages == ["en-US"] - assert entity.supported_options == [tts.ATTR_AUDIO_OUTPUT, tts.ATTR_VOICE] + assert entity.supported_options == [ + tts.ATTR_AUDIO_OUTPUT, + tts.ATTR_VOICE, + wyoming.ATTR_SPEAKER, + ] voices = entity.async_get_supported_voices("en-US") assert len(voices) == 1 assert voices[0].name == "Test Voice" @@ -137,3 +141,28 @@ async def test_get_tts_audio_audio_oserror( hass, "Hello world", "tts.test_tts", hass.config.language ), ) + + +async def test_voice_speaker(hass: HomeAssistant, init_wyoming_tts, snapshot) -> None: + """Test using a different voice and speaker.""" + audio = bytes(100) + audio_events = [ + AudioChunk(audio=audio, rate=16000, width=2, channels=1).event(), + AudioStop().event(), + ] + + with patch( + "homeassistant.components.wyoming.tts.AsyncTcpClient", + MockAsyncTcpClient(audio_events), + ) as mock_client: + await tts.async_get_media_source_audio( + hass, + tts.generate_media_source_id( + hass, + "Hello world", + "tts.test_tts", + "en-US", + options={tts.ATTR_VOICE: "voice1", wyoming.ATTR_SPEAKER: "speaker1"}, + ), + ) + assert mock_client.written == snapshot From 357af58c8128d75df513d3815c4e96e09e581ec1 Mon Sep 17 00:00:00 2001 From: Guido Schmitz Date: Fri, 14 Jul 2023 15:04:23 +0200 Subject: [PATCH 153/154] Bump devolo_plc_api to 1.3.2 (#96499) --- homeassistant/components/devolo_home_network/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/devolo_home_network/manifest.json b/homeassistant/components/devolo_home_network/manifest.json index e635b1f7021ca7..54b65c17e606ba 100644 --- a/homeassistant/components/devolo_home_network/manifest.json +++ b/homeassistant/components/devolo_home_network/manifest.json @@ -8,7 +8,7 @@ "iot_class": "local_polling", "loggers": ["devolo_plc_api"], "quality_scale": "platinum", - "requirements": ["devolo-plc-api==1.3.1"], + "requirements": ["devolo-plc-api==1.3.2"], "zeroconf": [ { "type": "_dvl-deviceapi._tcp.local.", diff --git a/requirements_all.txt b/requirements_all.txt index 74c409bc8c1023..b9bea4e24e20ea 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -655,7 +655,7 @@ denonavr==0.11.3 devolo-home-control-api==0.18.2 # homeassistant.components.devolo_home_network -devolo-plc-api==1.3.1 +devolo-plc-api==1.3.2 # homeassistant.components.directv directv==0.4.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 24f5987227f739..a11459908c01df 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -532,7 +532,7 @@ denonavr==0.11.3 devolo-home-control-api==0.18.2 # homeassistant.components.devolo_home_network -devolo-plc-api==1.3.1 +devolo-plc-api==1.3.2 # homeassistant.components.directv directv==0.4.0 From 1b7632a673b6b1bd59fc93ccbf81c3b532fd7305 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Fri, 14 Jul 2023 15:04:48 +0200 Subject: [PATCH 154/154] Support MyStrom switch 120 (#96535) --- homeassistant/components/mystrom/__init__.py | 4 ++-- tests/components/mystrom/test_init.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/mystrom/__init__.py b/homeassistant/components/mystrom/__init__.py index 972db00e476496..3166c05db19de1 100644 --- a/homeassistant/components/mystrom/__init__.py +++ b/homeassistant/components/mystrom/__init__.py @@ -53,7 +53,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: info.setdefault("type", 101) device_type = info["type"] - if device_type in [101, 106, 107]: + if device_type in [101, 106, 107, 120]: device = _get_mystrom_switch(host) platforms = PLATFORMS_SWITCH await _async_get_device_state(device, info["ip"]) @@ -86,7 +86,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload a config entry.""" device_type = hass.data[DOMAIN][entry.entry_id].info["type"] platforms = [] - if device_type in [101, 106, 107]: + if device_type in [101, 106, 107, 120]: platforms.extend(PLATFORMS_SWITCH) elif device_type in [102, 105]: platforms.extend(PLATFORMS_BULB) diff --git a/tests/components/mystrom/test_init.py b/tests/components/mystrom/test_init.py index 80011b47915398..4100a270e0a9c4 100644 --- a/tests/components/mystrom/test_init.py +++ b/tests/components/mystrom/test_init.py @@ -68,7 +68,7 @@ async def test_init_switch_and_unload( (110, "sensor", ConfigEntryState.SETUP_ERROR, True), (113, "switch", ConfigEntryState.SETUP_ERROR, True), (118, "button", ConfigEntryState.SETUP_ERROR, True), - (120, "switch", ConfigEntryState.SETUP_ERROR, True), + (120, "switch", ConfigEntryState.LOADED, False), ], ) async def test_init_bulb(