diff --git a/homeassistant/components/backup/manager.py b/homeassistant/components/backup/manager.py index e7fc1262f6d483..f1b2f7d5b976d3 100644 --- a/homeassistant/components/backup/manager.py +++ b/homeassistant/components/backup/manager.py @@ -1119,7 +1119,7 @@ async def _async_create_backup( ) if unavailable_agents: LOGGER.warning( - "Backup agents %s are not available, will backupp to %s", + "Backup agents %s are not available, will backup to %s", unavailable_agents, available_agents, ) diff --git a/homeassistant/components/esphome/config_flow.py b/homeassistant/components/esphome/config_flow.py index dc0e9b8e1b17ff..4efb0e494ef96a 100644 --- a/homeassistant/components/esphome/config_flow.py +++ b/homeassistant/components/esphome/config_flow.py @@ -316,10 +316,11 @@ async def _async_validate_mac_abort_configured( # Don't call _fetch_device_info() for ignored entries raise AbortFlow("already_configured") configured_host: str | None = entry.data.get(CONF_HOST) - configured_port: int | None = entry.data.get(CONF_PORT) - if configured_host == host and configured_port == port: + configured_port: int = entry.data.get(CONF_PORT, DEFAULT_PORT) + # When port is None (from DHCP discovery), only compare hosts + if configured_host == host and (port is None or configured_port == port): # Don't probe to verify the mac is correct since - # the host and port matches. + # the host matches (and port matches if provided). raise AbortFlow("already_configured") configured_psk: str | None = entry.data.get(CONF_NOISE_PSK) await self._fetch_device_info(host, port or configured_port, configured_psk) diff --git a/homeassistant/components/esphome/manifest.json b/homeassistant/components/esphome/manifest.json index 00d56955aa704c..355089555c5cc4 100644 --- a/homeassistant/components/esphome/manifest.json +++ b/homeassistant/components/esphome/manifest.json @@ -17,7 +17,7 @@ "mqtt": ["esphome/discover/#"], "quality_scale": "platinum", "requirements": [ - "aioesphomeapi==37.1.5", + "aioesphomeapi==37.1.6", "esphome-dashboard-api==1.3.0", "bleak-esphome==3.1.0" ], diff --git a/homeassistant/components/miele/const.py b/homeassistant/components/miele/const.py index a40df909e145cc..e8b626af785a8d 100644 --- a/homeassistant/components/miele/const.py +++ b/homeassistant/components/miele/const.py @@ -431,6 +431,16 @@ class StateDryingStep(MieleEnum): 38: "quick_power_wash", 42: "tall_items", 44: "power_wash", + 200: "eco", + 202: "automatic", + 203: "comfort_wash", + 204: "power_wash", + 205: "intensive", + 207: "extra_quiet", + 209: "comfort_wash_plus", + 210: "gentle", + 214: "maintenance", + 215: "rinse_salt", } TUMBLE_DRYER_PROGRAM_ID: dict[int, str] = { -1: "no_program", # Extrapolated from other device types. diff --git a/homeassistant/components/miele/sensor.py b/homeassistant/components/miele/sensor.py index 216b91ca68e74e..cc108841aae989 100644 --- a/homeassistant/components/miele/sensor.py +++ b/homeassistant/components/miele/sensor.py @@ -731,7 +731,7 @@ def native_value(self) -> StateType: ) ).name if self.device.state_plate_step - else PlatePowerStep.plate_step_0 + else PlatePowerStep.plate_step_0.name ) diff --git a/homeassistant/components/miele/services.py b/homeassistant/components/miele/services.py index 9854196ea652da..517b489173d367 100644 --- a/homeassistant/components/miele/services.py +++ b/homeassistant/components/miele/services.py @@ -203,7 +203,7 @@ async def get_programs(call: ServiceCall) -> ServiceResponse: else {} ), } - if item["parameters"] + if item.get("parameters") else {} ), } diff --git a/homeassistant/components/miele/strings.json b/homeassistant/components/miele/strings.json index 01f13c8550d9f9..a4400ff26ebbe8 100644 --- a/homeassistant/components/miele/strings.json +++ b/homeassistant/components/miele/strings.json @@ -485,6 +485,8 @@ "cook_bacon": "Cook bacon", "biscuits_short_crust_pastry_1_tray": "Biscuits, short crust pastry (1 tray)", "biscuits_short_crust_pastry_2_trays": "Biscuits, short crust pastry (2 trays)", + "comfort_wash": "Comfort wash", + "comfort_wash_plus": "Comfort wash plus", "cool_air": "Cool air", "corn_on_the_cob": "Corn on the cob", "cottons": "Cottons", @@ -827,6 +829,7 @@ "rice_pudding_steam_cooking": "Rice pudding (steam cooking)", "rinse": "Rinse", "rinse_out_lint": "Rinse out lint", + "rinse_salt": "Rinse salt", "risotto": "Risotto", "ristretto": "Ristretto", "roast_beef_low_temperature_cooking": "Roast beef (low temperature cooking)", diff --git a/homeassistant/components/mqtt/strings.json b/homeassistant/components/mqtt/strings.json index c14bda008d1c3a..40215b0f2c6031 100644 --- a/homeassistant/components/mqtt/strings.json +++ b/homeassistant/components/mqtt/strings.json @@ -802,15 +802,15 @@ "data": { "max_humidity": "Maximum humidity", "min_humidity": "Minimum humidity", - "target_humidity_command_template": "Humidity command template", - "target_humidity_command_topic": "Humidity command topic", - "target_humidity_state_template": "Humidity state template", - "target_humidity_state_topic": "Humidity state topic" + "target_humidity_command_template": "Target humidity command template", + "target_humidity_command_topic": "Target humidity command topic", + "target_humidity_state_template": "Target humidity state template", + "target_humidity_state_topic": "Target humidity state topic" }, "data_description": { "max_humidity": "The maximum target humidity that can be set.", "min_humidity": "The minimum target humidity that can be set.", - "target_humidity_command_template": "A [template](https://www.home-assistant.io/docs/configuration/templating/#using-command-templates-with-mqtt) to compose the payload to be published at the humidity command topic.", + "target_humidity_command_template": "A [template](https://www.home-assistant.io/docs/configuration/templating/#using-command-templates-with-mqtt) to compose the payload to be published at the target humidity command topic.", "target_humidity_command_topic": "The MQTT topic to publish commands to change the climate target humidity. [Learn more.]({url}#humidity_command_topic)", "target_humidity_state_template": "A [template](https://www.home-assistant.io/docs/configuration/templating/#using-value-templates-with-mqtt) to render the value received on the target humidity state topic with.", "target_humidity_state_topic": "The MQTT topic to subscribe for changes of the target humidity. [Learn more.]({url}#humidity_state_topic)" @@ -838,7 +838,7 @@ "temperature_low_state_topic": "Lower temperature state topic" }, "data_description": { - "initial": "The climate initalizes with this target temperature.", + "initial": "The climate initializes with this target temperature.", "max_temp": "The maximum target temperature that can be set.", "min_temp": "The minimum target temperature that can be set.", "precision": "The precision in degrees the thermostat is working at.", diff --git a/homeassistant/components/reolink/manifest.json b/homeassistant/components/reolink/manifest.json index 39541476429a3c..efd9f1121b6904 100644 --- a/homeassistant/components/reolink/manifest.json +++ b/homeassistant/components/reolink/manifest.json @@ -19,5 +19,5 @@ "iot_class": "local_push", "loggers": ["reolink_aio"], "quality_scale": "platinum", - "requirements": ["reolink-aio==0.14.4"] + "requirements": ["reolink-aio==0.14.5"] } diff --git a/homeassistant/components/template/strings.json b/homeassistant/components/template/strings.json index edf4516e8ab972..b412fa519cde66 100644 --- a/homeassistant/components/template/strings.json +++ b/homeassistant/components/template/strings.json @@ -2,6 +2,7 @@ "common": { "advanced_options": "Advanced options", "availability": "Availability template", + "availability_description": "Defines a template to get the `available` state of the entity. If the template either fails to render or returns `True`, `\"1\"`, `\"true\"`, `\"yes\"`, `\"on\"`, `\"enable\"`, or a non-zero number, the entity will be `available`. If the template returns any other value, the entity will be `unavailable`. If not configured, the entity will always be `available`. Note that the string comparison is not case sensitive; `\"TrUe\"` and `\"yEs\"` are allowed.", "code_format": "Code format", "device_class": "Device class", "device_id_description": "Select a device to link to this entity.", @@ -28,13 +29,26 @@ "code_format": "[%key:component::template::common::code_format%]" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "value_template": "Defines a template to set the state of the alarm panel. Valid output values from the template are `armed_away`, `armed_home`, `armed_night`, `armed_vacation`, `arming`, `disarmed`, `pending`, and `triggered`.", + "disarm": "Defines actions to run when the alarm control panel is disarmed. Receives variable `code`.", + "arm_away": "Defines actions to run when the alarm control panel is armed to `arm_away`. Receives variable `code`.", + "arm_custom_bypass": "Defines actions to run when the alarm control panel is armed to `arm_custom_bypass`. Receives variable `code`.", + "arm_home": "Defines actions to run when the alarm control panel is armed to `arm_home`. Receives variable `code`.", + "arm_night": "Defines actions to run when the alarm control panel is armed to `arm_night`. Receives variable `code`.", + "arm_vacation": "Defines actions to run when the alarm control panel is armed to `arm_vacation`. Receives variable `code`.", + "trigger": "Defines actions to run when the alarm control panel is triggered. Receives variable `code`.", + "code_arm_required": "If true, the code is required to arm the alarm.", + "code_format": "One of number, text or no_code. Format for the code used to arm/disarm the alarm." }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -48,13 +62,17 @@ "state": "[%key:component::template::common::state%]" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "state": "The sensor is `on` if the template evaluates as `True`, `yes`, `on`, `enable` or a positive number. Any other value will render it as `off`." }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -68,13 +86,17 @@ "press": "Actions on press" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "press": "Defines actions to run when button is pressed." }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -99,13 +121,16 @@ "close_cover": "Defines actions to run when the cover is closed.", "stop_cover": "Defines actions to run when the cover is stopped.", "position": "Defines a template to get the position of the cover. Value values are numbers between `0` (`closed`) and `100` (`open`).", - "set_cover_position": "Defines actions to run when the cover is given a `set_cover_position` command." + "set_cover_position": "Defines actions to run when the cover is given a `set_cover_position` command. Receives variable `position`." }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -124,11 +149,11 @@ }, "data_description": { "device_id": "[%key:component::template::common::device_id_description%]", - "state": "Defines a template to get the state of the fan. Valid values: `on`, `off`.", + "state": "The fan is `on` if the template evaluates as `True`, `yes`, `on`, `enable` or a positive number. Any other value will render it as `off`.", "turn_off": "Defines actions to run when the fan is turned off.", - "turn_on": "Defines actions to run when the fan is turned on.", + "turn_on": "Defines actions to run when the fan is turned on. Receives variables `percentage` and/or `preset_mode`.", "percentage": "Defines a template to get the speed percentage of the fan.", - "set_percentage": "Defines actions to run when the fan is given a speed percentage command.", + "set_percentage": "Defines actions to run when the fan is given a speed percentage command. Receives variable `percentage`.", "speed_count": "The number of speeds the fan supports. Used to calculate the percentage step for the `fan.increase_speed` and `fan.decrease_speed` actions." }, "sections": { @@ -136,6 +161,9 @@ "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -149,13 +177,18 @@ "verify_ssl": "[%key:common::config_flow::data::verify_ssl%]" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "url": "Defines a template to get the URL on which the image is served.", + "verify_ssl": "Enable or disable SSL certificate verification. Disable to use an http-only URL, or if you have a self-signed SSL certificate and haven’t installed the CA certificate to enable verification." }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -176,13 +209,25 @@ "set_temperature": "Actions on set color temperature" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "state": "The light is `on` if the template evaluates as `True`, `yes`, `on`, `enable` or a positive number. Any other value will render it as `off`.", + "turn_off": "Defines actions to run when the light is turned off.", + "turn_on": "Defines actions to run when the light is turned on.", + "level": "Defines a template to get the brightness of the light. Valid values are 0 to 255.", + "set_level": "Defines actions to run when the light is given a brightness command. The script will only be called if the `turn_on` call only has `brightness`, and optionally `transition`. Receives variables `brightness` and, optionally, `transition`.", + "hs": "Defines a template to get the HS color of the light. Must render a tuple (hue, saturation).", + "set_hs": "Defines actions to run when the light is given a hs color command. Available variables: `hs` as a tuple, `h` and `s`.", + "temperature": "Defines a template to get the color temperature of the light.", + "set_temperature": "Defines actions to run when the light is given a color temperature command. Receives variable `color_temp_kelvin`. May also receive variables `brightness` and/or `transition`." }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -199,13 +244,21 @@ "open": "Actions on open" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "state": "Defines a template to set the state of the lock. The lock is locked if the template evaluates to `True`, `true`, `on`, or `locked`. The lock is unlocked if the template evaluates to `False`, `false`, `off`, or `unlocked`. Other valid states are `jammed`, `opening`, `locking`, `open`, and `unlocking`.", + "lock": "Defines actions to run when the lock is locked.", + "unlock": "Defines actions to run when the lock is unlocked.", + "code_format": "Defines a template to get the `code_format` attribute of the lock.", + "open": "Defines actions to run when the lock is opened." }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -223,13 +276,22 @@ "unit_of_measurement": "[%key:component::template::common::unit_of_measurement%]" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "state": "Template for the number's current value.", + "step": "Template for the number's increment/decrement step.", + "set_value": "Defines actions to run when the number is set to a value. Receives variable `value`.", + "max": "Template for the number's maximum value.", + "min": "Template for the number's minimum value.", + "unit_of_measurement": "Defines the units of measurement of the number, if any." }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -244,13 +306,19 @@ "options": "Available options" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "state": "Template for the select’s current value.", + "select_option": "Defines actions to run when an `option` from the `options` list is selected. Receives variable `option`.", + "options": "Template for the select’s available options." }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -266,13 +334,18 @@ "unit_of_measurement": "[%key:component::template::common::unit_of_measurement%]" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "state": "Defines a template to get the state of the sensor. If the sensor is numeric, i.e. it has a `state_class` or a `unit_of_measurement`, the state template must render to a number or to `none`. The state template must not render to a string, including `unknown` or `unavailable`. An `availability` template may be defined to suppress rendering of the state template.", + "unit_of_measurement": "Defines the units of measurement of the sensor, if any. This will also display the value based on the number format setting in the user profile and influence the graphical presentation in the history visualization as a continuous value." }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -307,13 +380,18 @@ }, "data_description": { "device_id": "[%key:component::template::common::device_id_description%]", - "value_template": "Defines a template to set the state of the switch. If not defined, the switch will optimistically assume all commands are successful." + "value_template": "Defines a template to set the state of the switch. If not defined, the switch will optimistically assume all commands are successful.", + "turn_off": "Defines actions to run when the switch is turned off.", + "turn_on": "Defines actions to run when the switch is turned on." }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -324,24 +402,37 @@ "device_id": "[%key:common::config_flow::data::device%]", "name": "[%key:common::config_flow::data::name%]", "state": "[%key:component::template::common::state%]", - "start": "Actions on turn off", + "start": "Actions on start", "fan_speed": "Fan speed", "fan_speeds": "Fan speeds", "set_fan_speed": "Actions on set fan speed", "stop": "Actions on stop", "pause": "Actions on pause", - "return_to_base": "Actions on return to base", + "return_to_base": "Actions on return to dock", "clean_spot": "Actions on clean spot", "locate": "Actions on locate" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "state": "Defines a template to get the state of the vacuum. Valid values are `cleaning`, `docked`, `idle`, `paused`, `returning`, and `error`.", + "start": "Defines actions to run when the vacuum is started.", + "fan_speed": "Defines a template to get the fan speed of the vacuum.", + "fan_speeds": "List of fan speeds supported by the vacuum.", + "set_fan_speed": "Defines actions to run when the vacuum is given a command to set the fan speed. Receives variable `fan_speed`", + "stop": "Defines actions to run when the vacuum is stopped.", + "pause": "Defines actions to run when the vacuum is paused.", + "return_to_base": "Defines actions to run when the vacuum is given a 'Return to dock' command.", + "clean_spot": "Defines actions to run when the vacuum is given a 'Clean spot' command.", + "locate": "Defines actions to run when the vacuum is given a 'Locate' command." }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -366,13 +457,26 @@ "code_format": "[%key:component::template::common::code_format%]" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "value_template": "[%key:component::template::config::step::alarm_control_panel::data_description::value_template%]", + "disarm": "[%key:component::template::config::step::alarm_control_panel::data_description::disarm%]", + "arm_away": "[%key:component::template::config::step::alarm_control_panel::data_description::arm_away%]", + "arm_custom_bypass": "[%key:component::template::config::step::alarm_control_panel::data_description::arm_custom_bypass%]", + "arm_home": "[%key:component::template::config::step::alarm_control_panel::data_description::arm_home%]", + "arm_night": "[%key:component::template::config::step::alarm_control_panel::data_description::arm_night%]", + "arm_vacation": "[%key:component::template::config::step::alarm_control_panel::data_description::arm_vacation%]", + "trigger": "[%key:component::template::config::step::alarm_control_panel::data_description::trigger%]", + "code_arm_required": "[%key:component::template::config::step::alarm_control_panel::data_description::code_arm_required%]", + "code_format": "[%key:component::template::config::step::alarm_control_panel::data_description::code_format%]" }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -384,13 +488,17 @@ "state": "[%key:component::template::common::state%]" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "state": "[%key:component::template::config::step::binary_sensor::data_description::state%]" }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -402,13 +510,17 @@ "press": "[%key:component::template::config::step::button::data::press%]" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "press": "[%key:component::template::config::step::button::data_description::press%]" }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -439,6 +551,9 @@ "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -468,6 +583,9 @@ "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -480,13 +598,18 @@ "verify_ssl": "[%key:common::config_flow::data::verify_ssl%]" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "url": "[%key:component::template::config::step::image::data_description::url%]", + "verify_ssl": "[%key:component::template::config::step::image::data_description::verify_ssl%]" }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -507,13 +630,25 @@ "set_temperature": "[%key:component::template::config::step::light::data::set_temperature%]" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "state": "[%key:component::template::config::step::light::data_description::state%]", + "turn_off": "[%key:component::template::config::step::light::data_description::turn_off%]", + "turn_on": "[%key:component::template::config::step::light::data_description::turn_on%]", + "level": "[%key:component::template::config::step::light::data_description::level%]", + "set_level": "[%key:component::template::config::step::light::data_description::set_level%]", + "hs": "[%key:component::template::config::step::light::data_description::hs%]", + "set_hs": "[%key:component::template::config::step::light::data_description::set_hs%]", + "temperature": "[%key:component::template::config::step::light::data_description::temperature%]", + "set_temperature": "[%key:component::template::config::step::light::data_description::set_temperature%]" }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -529,13 +664,21 @@ "open": "[%key:component::template::config::step::lock::data::open%]" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "state": "[%key:component::template::config::step::lock::data_description::state%]", + "lock": "[%key:component::template::config::step::lock::data_description::lock%]", + "unlock": "[%key:component::template::config::step::lock::data_description::unlock%]", + "code_format": "[%key:component::template::config::step::lock::data_description::code_format%]", + "open": "[%key:component::template::config::step::lock::data_description::open%]" }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -552,13 +695,21 @@ "min": "[%key:component::template::config::step::number::data::min%]" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "state": "[%key:component::template::config::step::number::data_description::state%]", + "step": "[%key:component::template::config::step::number::data_description::step%]", + "set_value": "[%key:component::template::config::step::number::data_description::set_value%]", + "max": "[%key:component::template::config::step::number::data_description::max%]", + "min": "[%key:component::template::config::step::number::data_description::min%]" }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -573,13 +724,19 @@ "options": "[%key:component::template::config::step::select::data::options%]" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "state": "[%key:component::template::config::step::select::data_description::state%]", + "select_option": "[%key:component::template::config::step::select::data_description::select_option%]", + "options": "[%key:component::template::config::step::select::data_description::options%]" }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -594,13 +751,18 @@ "unit_of_measurement": "[%key:component::template::common::unit_of_measurement%]" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "state": "[%key:component::template::config::step::sensor::data_description::state%]", + "unit_of_measurement": "[%key:component::template::config::step::sensor::data_description::state%]" }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -616,13 +778,18 @@ }, "data_description": { "device_id": "[%key:component::template::common::device_id_description%]", - "value_template": "[%key:component::template::config::step::switch::data_description::value_template%]" + "value_template": "[%key:component::template::config::step::switch::data_description::value_template%]", + "turn_off": "[%key:component::template::config::step::switch::data_description::turn_off%]", + "turn_on": "[%key:component::template::config::step::switch::data_description::turn_on%]" }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, @@ -644,17 +811,30 @@ "locate": "[%key:component::template::config::step::vacuum::data::locate%]" }, "data_description": { - "device_id": "[%key:component::template::common::device_id_description%]" + "device_id": "[%key:component::template::common::device_id_description%]", + "state": "[%key:component::template::config::step::vacuum::data_description::state%]", + "start": "[%key:component::template::config::step::vacuum::data_description::start%]", + "fan_speed": "[%key:component::template::config::step::vacuum::data_description::fan_speed%]", + "fan_speeds": "[%key:component::template::config::step::vacuum::data_description::fan_speeds%]", + "set_fan_speed": "[%key:component::template::config::step::vacuum::data_description::set_fan_speed%]", + "stop": "[%key:component::template::config::step::vacuum::data_description::stop%]", + "pause": "[%key:component::template::config::step::vacuum::data_description::pause%]", + "return_to_base": "[%key:component::template::config::step::vacuum::data_description::return_to_base%]", + "clean_spot": "[%key:component::template::config::step::vacuum::data_description::clean_spot%]", + "locate": "[%key:component::template::config::step::vacuum::data_description::locate%]" }, "sections": { "advanced_options": { "name": "[%key:component::template::common::advanced_options%]", "data": { "availability": "[%key:component::template::common::availability%]" + }, + "data_description": { + "availability": "[%key:component::template::common::availability_description%]" } } }, - "title": "Template vacuum" + "title": "[%key:component::template::config::step::vacuum::title%]" } } }, diff --git a/requirements_all.txt b/requirements_all.txt index f5f0c5116dc165..2af9a9f712df93 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -247,7 +247,7 @@ aioelectricitymaps==0.4.0 aioemonitor==1.0.5 # homeassistant.components.esphome -aioesphomeapi==37.1.5 +aioesphomeapi==37.1.6 # homeassistant.components.flo aioflo==2021.11.0 @@ -2666,7 +2666,7 @@ renault-api==0.3.1 renson-endura-delta==1.7.2 # homeassistant.components.reolink -reolink-aio==0.14.4 +reolink-aio==0.14.5 # homeassistant.components.idteck_prox rfk101py==0.0.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 9336bbcc68cdfb..bbfcb8b24350ba 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -235,7 +235,7 @@ aioelectricitymaps==0.4.0 aioemonitor==1.0.5 # homeassistant.components.esphome -aioesphomeapi==37.1.5 +aioesphomeapi==37.1.6 # homeassistant.components.flo aioflo==2021.11.0 @@ -2212,7 +2212,7 @@ renault-api==0.3.1 renson-endura-delta==1.7.2 # homeassistant.components.reolink -reolink-aio==0.14.4 +reolink-aio==0.14.5 # homeassistant.components.rflink rflink==0.0.67 diff --git a/tests/components/esphome/test_config_flow.py b/tests/components/esphome/test_config_flow.py index d76991a984c24f..0fda7714dd01ae 100644 --- a/tests/components/esphome/test_config_flow.py +++ b/tests/components/esphome/test_config_flow.py @@ -2485,3 +2485,36 @@ async def test_reconfig_name_conflict_overwrite( ) is None ) + + +@pytest.mark.usefixtures("mock_setup_entry") +async def test_discovery_dhcp_no_probe_same_host_port_none( + hass: HomeAssistant, mock_client: APIClient +) -> None: + """Test dhcp discovery does not probe when host matches and port is None.""" + entry = MockConfigEntry( + domain=DOMAIN, + data={CONF_HOST: "192.168.43.183", CONF_PORT: 6053, CONF_PASSWORD: ""}, + unique_id="11:22:33:44:55:aa", + ) + entry.add_to_hass(hass) + + # DHCP discovery with same MAC and host (WiFi device) + service_info = DhcpServiceInfo( + ip="192.168.43.183", + hostname="test8266", + macaddress="11:22:33:44:55:aa", # Same MAC as configured + ) + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_DHCP}, data=service_info + ) + + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "already_configured" + + # Verify device_info was NOT called (no probing) + mock_client.device_info.assert_not_called() + + # Host should remain unchanged + assert entry.data[CONF_HOST] == "192.168.43.183" diff --git a/tests/components/miele/fixtures/programs.json b/tests/components/miele/fixtures/programs.json index ce2348f61de9d6..1c232059d59a3d 100644 --- a/tests/components/miele/fixtures/programs.json +++ b/tests/components/miele/fixtures/programs.json @@ -30,5 +30,9 @@ "mandatory": true } } + }, + { + "programId": 24000, + "program": "Ristretto" } ] diff --git a/tests/components/miele/snapshots/test_sensor.ambr b/tests/components/miele/snapshots/test_sensor.ambr index 915eda4d3615ee..2805a6830773dc 100644 --- a/tests/components/miele/snapshots/test_sensor.ambr +++ b/tests/components/miele/snapshots/test_sensor.ambr @@ -1,4 +1,1141 @@ # serializer version: 1 +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'autocleaning', + 'failure', + 'idle', + 'in_use', + 'not_connected', + 'off', + 'on', + 'pause', + 'program_ended', + 'program_interrupted', + 'programmed', + 'rinse_hold', + 'service', + 'supercooling', + 'supercooling_superfreezing', + 'superfreezing', + 'superheating', + 'waiting_to_start', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.hob_with_extraction', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': 'mdi:pot-steam-outline', + 'original_name': None, + 'platform': 'miele', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'status', + 'unique_id': 'DummyAppliance_74-state_status', + 'unit_of_measurement': None, + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Hob with extraction', + 'icon': 'mdi:pot-steam-outline', + 'options': list([ + 'autocleaning', + 'failure', + 'idle', + 'in_use', + 'not_connected', + 'off', + 'on', + 'pause', + 'program_ended', + 'program_interrupted', + 'programmed', + 'rinse_hold', + 'service', + 'supercooling', + 'supercooling_superfreezing', + 'superfreezing', + 'superheating', + 'waiting_to_start', + ]), + }), + 'context': , + 'entity_id': 'sensor.hob_with_extraction', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'in_use', + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_2-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'autocleaning', + 'failure', + 'idle', + 'in_use', + 'not_connected', + 'off', + 'on', + 'pause', + 'program_ended', + 'program_interrupted', + 'programmed', + 'rinse_hold', + 'service', + 'supercooling', + 'supercooling_superfreezing', + 'superfreezing', + 'superheating', + 'waiting_to_start', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.hob_with_extraction_2', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': 'mdi:pot-steam-outline', + 'original_name': None, + 'platform': 'miele', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'status', + 'unique_id': 'DummyAppliance_74_off-state_status', + 'unit_of_measurement': None, + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_2-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Hob with extraction', + 'icon': 'mdi:pot-steam-outline', + 'options': list([ + 'autocleaning', + 'failure', + 'idle', + 'in_use', + 'not_connected', + 'off', + 'on', + 'pause', + 'program_ended', + 'program_interrupted', + 'programmed', + 'rinse_hold', + 'service', + 'supercooling', + 'supercooling_superfreezing', + 'superfreezing', + 'superheating', + 'waiting_to_start', + ]), + }), + 'context': , + 'entity_id': 'sensor.hob_with_extraction_2', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_1-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.hob_with_extraction_plate_1', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Plate 1', + 'platform': 'miele', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'plate', + 'unique_id': 'DummyAppliance_74-state_plate_step-1', + 'unit_of_measurement': None, + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_1-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Hob with extraction Plate 1', + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'context': , + 'entity_id': 'sensor.hob_with_extraction_plate_1', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'plate_step_0', + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_1_2-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.hob_with_extraction_plate_1_2', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Plate 1', + 'platform': 'miele', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'plate', + 'unique_id': 'DummyAppliance_74_off-state_plate_step-1', + 'unit_of_measurement': None, + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_1_2-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Hob with extraction Plate 1', + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'context': , + 'entity_id': 'sensor.hob_with_extraction_plate_1_2', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'plate_step_0', + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_2-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.hob_with_extraction_plate_2', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Plate 2', + 'platform': 'miele', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'plate', + 'unique_id': 'DummyAppliance_74-state_plate_step-2', + 'unit_of_measurement': None, + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_2-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Hob with extraction Plate 2', + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'context': , + 'entity_id': 'sensor.hob_with_extraction_plate_2', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'plate_step_3', + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_2_2-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.hob_with_extraction_plate_2_2', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Plate 2', + 'platform': 'miele', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'plate', + 'unique_id': 'DummyAppliance_74_off-state_plate_step-2', + 'unit_of_measurement': None, + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_2_2-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Hob with extraction Plate 2', + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'context': , + 'entity_id': 'sensor.hob_with_extraction_plate_2_2', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'plate_step_0', + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_3-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.hob_with_extraction_plate_3', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Plate 3', + 'platform': 'miele', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'plate', + 'unique_id': 'DummyAppliance_74-state_plate_step-3', + 'unit_of_measurement': None, + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_3-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Hob with extraction Plate 3', + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'context': , + 'entity_id': 'sensor.hob_with_extraction_plate_3', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'plate_step_7', + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_3_2-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.hob_with_extraction_plate_3_2', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Plate 3', + 'platform': 'miele', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'plate', + 'unique_id': 'DummyAppliance_74_off-state_plate_step-3', + 'unit_of_measurement': None, + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_3_2-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Hob with extraction Plate 3', + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'context': , + 'entity_id': 'sensor.hob_with_extraction_plate_3_2', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'plate_step_0', + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_4-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.hob_with_extraction_plate_4', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Plate 4', + 'platform': 'miele', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'plate', + 'unique_id': 'DummyAppliance_74-state_plate_step-4', + 'unit_of_measurement': None, + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_4-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Hob with extraction Plate 4', + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'context': , + 'entity_id': 'sensor.hob_with_extraction_plate_4', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'plate_step_15', + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_4_2-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.hob_with_extraction_plate_4_2', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Plate 4', + 'platform': 'miele', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'plate', + 'unique_id': 'DummyAppliance_74_off-state_plate_step-4', + 'unit_of_measurement': None, + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_4_2-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Hob with extraction Plate 4', + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'context': , + 'entity_id': 'sensor.hob_with_extraction_plate_4_2', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'plate_step_0', + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_5-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.hob_with_extraction_plate_5', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Plate 5', + 'platform': 'miele', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'plate', + 'unique_id': 'DummyAppliance_74-state_plate_step-5', + 'unit_of_measurement': None, + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hob_with_extraction_plate_5-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Hob with extraction Plate 5', + 'options': list([ + 'plate_step_0', + 'plate_step_1', + 'plate_step_10', + 'plate_step_11', + 'plate_step_12', + 'plate_step_13', + 'plate_step_14', + 'plate_step_15', + 'plate_step_16', + 'plate_step_17', + 'plate_step_18', + 'plate_step_2', + 'plate_step_3', + 'plate_step_4', + 'plate_step_5', + 'plate_step_6', + 'plate_step_7', + 'plate_step_8', + 'plate_step_9', + 'plate_step_boost', + 'plate_step_warming', + ]), + }), + 'context': , + 'entity_id': 'sensor.hob_with_extraction_plate_5', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'plate_step_boost', + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hood-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'autocleaning', + 'failure', + 'idle', + 'in_use', + 'not_connected', + 'off', + 'on', + 'pause', + 'program_ended', + 'program_interrupted', + 'programmed', + 'rinse_hold', + 'service', + 'supercooling', + 'supercooling_superfreezing', + 'superfreezing', + 'superheating', + 'waiting_to_start', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.hood', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': 'mdi:turbine', + 'original_name': None, + 'platform': 'miele', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'status', + 'unique_id': 'DummyAppliance_18-state_status', + 'unit_of_measurement': None, + }) +# --- +# name: test_fan_hob_sensor_states[platforms0-fan_devices.json][sensor.hood-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Hood', + 'icon': 'mdi:turbine', + 'options': list([ + 'autocleaning', + 'failure', + 'idle', + 'in_use', + 'not_connected', + 'off', + 'on', + 'pause', + 'program_ended', + 'program_interrupted', + 'programmed', + 'rinse_hold', + 'service', + 'supercooling', + 'supercooling_superfreezing', + 'superfreezing', + 'superheating', + 'waiting_to_start', + ]), + }), + 'context': , + 'entity_id': 'sensor.hood', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- # name: test_fridge_freezer_sensor_states[platforms0-fridge_freezer.json][sensor.fridge_freezer-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ diff --git a/tests/components/miele/snapshots/test_services.ambr b/tests/components/miele/snapshots/test_services.ambr index 3095ec9b6fbea0..3c3feca7832606 100644 --- a/tests/components/miele/snapshots/test_services.ambr +++ b/tests/components/miele/snapshots/test_services.ambr @@ -43,6 +43,12 @@ 'program': 'Fan plus', 'program_id': 13, }), + dict({ + 'parameters': dict({ + }), + 'program': 'Ristretto', + 'program_id': 24000, + }), ]), }) # --- diff --git a/tests/components/miele/test_sensor.py b/tests/components/miele/test_sensor.py index f35404a665bdfd..e5051a683c9a71 100644 --- a/tests/components/miele/test_sensor.py +++ b/tests/components/miele/test_sensor.py @@ -256,3 +256,18 @@ async def test_vacuum_sensor_states( """Test robot vacuum cleaner sensor state.""" await snapshot_platform(hass, entity_registry, snapshot, setup_platform.entry_id) + + +@pytest.mark.parametrize("load_device_file", ["fan_devices.json"]) +@pytest.mark.parametrize("platforms", [(SENSOR_DOMAIN,)]) +@pytest.mark.usefixtures("entity_registry_enabled_by_default") +async def test_fan_hob_sensor_states( + hass: HomeAssistant, + mock_miele_client: MagicMock, + snapshot: SnapshotAssertion, + entity_registry: er.EntityRegistry, + setup_platform: None, +) -> None: + """Test robot fan / hob sensor state.""" + + await snapshot_platform(hass, entity_registry, snapshot, setup_platform.entry_id)