From 72b81a1021947e2d511a7c9085cf34b1a605291f Mon Sep 17 00:00:00 2001 From: gielk Date: Thu, 21 May 2026 11:18:45 +0200 Subject: [PATCH 1/7] Add washing machine and dryer cycle/operating state sensors to SmartThings --- .../components/smartthings/sensor.py | 116 ++++++++++++++++++ .../components/smartthings/strings.json | 64 ++++++++++ 2 files changed, 180 insertions(+) diff --git a/homeassistant/components/smartthings/sensor.py b/homeassistant/components/smartthings/sensor.py index a057be0ebd312..01ef73997413f 100644 --- a/homeassistant/components/smartthings/sensor.py +++ b/homeassistant/components/smartthings/sensor.py @@ -38,6 +38,7 @@ from .entity import SmartThingsEntity from .util import deprecate_entity + THERMOSTAT_CAPABILITIES = { Capability.TEMPERATURE_MEASUREMENT, Capability.THERMOSTAT_HEATING_SETPOINT, @@ -143,6 +144,55 @@ WASHER_OPTIONS = ["pause", "run", "stop"] +WASHER_CYCLES = [ + "1c", + "2b", + "1b", + "1e", + "1d", + "96", + "8f", + "25", + "26", + "33", + "24", + "32", + "20", + "22", + "23", + "2f", + "21", + "66", + "2e", + "2d", + "30", + "29", + "27", + "28", +] + +DRYER_CYCLES = [ + "51", + "53", + "23", + "17", + "18", + "19", + "1d", + "1b", + "1c", + "21", + "1a", + "1e", + "20", + "27", + "25", + "24", + "4e", + "4c", +] + + def power_attributes(status: dict[str, Any]) -> dict[str, Any]: """Return the power attributes.""" @@ -1278,6 +1328,68 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription): ) ] }, + "samsungce.washerCycle": { + "washerCycle": [ + SmartThingsSensorEntityDescription( + key="washerCycle", + translation_key="washer_cycle", + icon="mdi:washing-machine", + options=WASHER_CYCLES, + device_class=SensorDeviceClass.ENUM, + ) + ] + }, + "samsungce.dryerCycle": { + "dryerCycle": [ + SmartThingsSensorEntityDescription( + key="dryerCycle", + translation_key="dryer_cycle", + icon="mdi:tumble-dryer", + options=DRYER_CYCLES, + device_class=SensorDeviceClass.ENUM, + ) + ] + }, + "samsungce.washerOperatingState": { + "progress": [ + SmartThingsSensorEntityDescription( + key="progress", + translation_key="washer_progress", + icon="mdi:washing-machine", + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=PERCENTAGE, + ) + ], + "remainingTime": [ + SmartThingsSensorEntityDescription( + key="remainingTime", + translation_key="washer_remaining_time", + icon="mdi:timer-sand", + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement="min", + ) + ] + }, + "samsungce.dryerOperatingState": { + "progress": [ + SmartThingsSensorEntityDescription( + key="progress", + translation_key="dryer_progress", + icon="mdi:tumble-dryer", + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=PERCENTAGE, + ) + ], + "remainingTime": [ + SmartThingsSensorEntityDescription( + key="remainingTime", + translation_key="dryer_remaining_time", + icon="mdi:timer-sand", + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement="min", + ) + ] + }, } @@ -1424,6 +1536,10 @@ def __init__( def native_value(self) -> str | float | datetime | int | None: """Return the state of the sensor.""" res = self.get_attribute_value(self.capability, self._attribute) + if self.capability in ("samsungce.washerCycle", "samsungce.dryerCycle"): + if not res: + return None + return res.split("_")[-1].lower() if "_" in res else res.lower() if options_map := self.entity_description.options_map: return options_map.get(res) value = self.entity_description.value_fn(res) diff --git a/homeassistant/components/smartthings/strings.json b/homeassistant/components/smartthings/strings.json index cf4653c55cb47..1aa36e103bd32 100644 --- a/homeassistant/components/smartthings/strings.json +++ b/homeassistant/components/smartthings/strings.json @@ -947,6 +947,70 @@ "stop": "[%key:common::state::stopped%]" } }, + "washer_cycle": { + "name": "Washer cycle", + "state": { + "1c": "Eco 40-60", + "2b": "AI Wash", + "1b": "Cotton", + "1e": "15' Quick Wash", + "1d": "Super Speed", + "96": "Less Microfiber", + "8f": "Intense Cold", + "25": "Synthetics", + "26": "Delicates", + "33": "Towels", + "24": "Bedding", + "32": "Shirts", + "20": "Hygiene Steam", + "22": "Wool", + "23": "Outdoor", + "2f": "Activewear", + "21": "Colors", + "66": "Denim", + "2e": "Baby Care", + "2d": "Silent Wash", + "30": "Cloudy day", + "29": "Drum Clean+", + "27": "Rinse+Spin", + "28": "Drain/Spin" + } + }, + "dryer_cycle": { + "name": "Dryer cycle", + "state": { + "51": "Eco Cotton", + "53": "AI Dry+", + "23": "Quick Dry 35'", + "17": "Super Speed", + "18": "Synthetics", + "19": "Delicates", + "1d": "Towels", + "1b": "Bedding", + "1c": "Shirts", + "21": "Hygiene Care", + "1a": "Wool", + "1e": "Outdoor", + "20": "Iron Dry", + "27": "Time Dry", + "25": "Warm Air", + "24": "Cool Air", + "4e": "Self Dry", + "4c": "Air Refresh" + } + }, + "washer_progress": { + "name": "Washing progress" + }, + "dryer_progress": { + "name": "Drying progress" + }, + "washer_remaining_time": { + "name": "Washer remaining time" + }, + "dryer_remaining_time": { + "name": "Dryer remaining time" + }, "washer_mode": { "name": "Washer mode" }, From de2014d0ef76d1e921427eb04dd6c36221f742aa Mon Sep 17 00:00:00 2001 From: Giel Date: Thu, 21 May 2026 11:23:24 +0200 Subject: [PATCH 2/7] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- homeassistant/components/smartthings/strings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/smartthings/strings.json b/homeassistant/components/smartthings/strings.json index 1aa36e103bd32..be0ffa053905b 100644 --- a/homeassistant/components/smartthings/strings.json +++ b/homeassistant/components/smartthings/strings.json @@ -970,7 +970,7 @@ "66": "Denim", "2e": "Baby Care", "2d": "Silent Wash", - "30": "Cloudy day", + "30": "Cloudy Day", "29": "Drum Clean+", "27": "Rinse+Spin", "28": "Drain/Spin" From 9e9f6745f5de6a3bb12e29b8fa9b97c48f17fe1b Mon Sep 17 00:00:00 2001 From: gielk Date: Thu, 21 May 2026 11:36:21 +0200 Subject: [PATCH 3/7] Address Codex review feedback: dynamically fetch washer/dryer cycles from supportedCycles --- .../components/smartthings/sensor.py | 76 ++++++++++++++----- .../components/smartthings/strings.json | 2 +- 2 files changed, 60 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/smartthings/sensor.py b/homeassistant/components/smartthings/sensor.py index 01ef73997413f..d98e1cb5d283e 100644 --- a/homeassistant/components/smartthings/sensor.py +++ b/homeassistant/components/smartthings/sensor.py @@ -26,6 +26,7 @@ UnitOfPower, UnitOfPressure, UnitOfTemperature, + UnitOfTime, UnitOfVolume, ) from homeassistant.core import HomeAssistant @@ -38,7 +39,6 @@ from .entity import SmartThingsEntity from .util import deprecate_entity - THERMOSTAT_CAPABILITIES = { Capability.TEMPERATURE_MEASUREMENT, Capability.THERMOSTAT_HEATING_SETPOINT, @@ -203,6 +203,14 @@ def power_attributes(status: dict[str, Any]) -> dict[str, Any]: return state +def _normalize_cycle_value(value: Any) -> str | None: + """Normalize washer/dryer cycle names.""" + if not value: + return None + value_str = str(value) + return value_str.split("_")[-1].lower() if "_" in value_str else value_str.lower() + + @dataclass(frozen=True, kw_only=True) class SmartThingsSensorEntityDescription(SensorEntityDescription): """Describe a SmartThings sensor entity.""" @@ -1335,7 +1343,9 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription): translation_key="washer_cycle", icon="mdi:washing-machine", options=WASHER_CYCLES, + options_attribute=Attribute.SUPPORTED_CYCLES, device_class=SensorDeviceClass.ENUM, + value_fn=_normalize_cycle_value, ) ] }, @@ -1346,7 +1356,9 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription): translation_key="dryer_cycle", icon="mdi:tumble-dryer", options=DRYER_CYCLES, + options_attribute=Attribute.SUPPORTED_CYCLES, device_class=SensorDeviceClass.ENUM, + value_fn=_normalize_cycle_value, ) ] }, @@ -1366,7 +1378,8 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription): translation_key="washer_remaining_time", icon="mdi:timer-sand", state_class=SensorStateClass.MEASUREMENT, - native_unit_of_measurement="min", + device_class=SensorDeviceClass.DURATION, + native_unit_of_measurement=UnitOfTime.MINUTES, ) ] }, @@ -1386,7 +1399,8 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription): translation_key="dryer_remaining_time", icon="mdi:timer-sand", state_class=SensorStateClass.MEASUREMENT, - native_unit_of_measurement="min", + device_class=SensorDeviceClass.DURATION, + native_unit_of_measurement=UnitOfTime.MINUTES, ) ] }, @@ -1536,10 +1550,6 @@ def __init__( def native_value(self) -> str | float | datetime | int | None: """Return the state of the sensor.""" res = self.get_attribute_value(self.capability, self._attribute) - if self.capability in ("samsungce.washerCycle", "samsungce.dryerCycle"): - if not res: - return None - return res.split("_")[-1].lower() if "_" in res else res.lower() if options_map := self.entity_description.options_map: return options_map.get(res) value = self.entity_description.value_fn(res) @@ -1577,13 +1587,45 @@ def extra_state_attributes(self) -> Mapping[str, Any] | None: def options(self) -> list[str] | None: """Return the options for this sensor.""" if self.entity_description.options_attribute: - if ( - options := self.get_attribute_value( - self.capability, self.entity_description.options_attribute - ) - ) is None: - return [] - if options_map := self.entity_description.options_map: - return [options_map[option] for option in options] - return [option.lower() for option in options] - return super().options + options_val = self.get_attribute_value( + self.capability, self.entity_description.options_attribute + ) + if options_val is not None: + options_list = [] + for option in options_val: + if isinstance(option, dict): + opt_str = option.get("cycle") + else: + opt_str = option + if opt_str is not None: + opt_str = str(opt_str) + if options_map := self.entity_description.options_map: + opt_str = options_map.get(opt_str, opt_str) + options_list.append(opt_str.lower()) + + # Guard against rejection: append current state if not present + if (current_value := self.native_value) is not None: + current_value_str = str(current_value) + if current_value_str not in options_list: + options_list.append(current_value_str) + return options_list + + # Fall back to static options in description if attribute is missing/None + if (static_options := super().options) is not None: + options_list = list(static_options) + if (current_value := self.native_value) is not None: + current_value_str = str(current_value) + if current_value_str not in options_list: + options_list.append(current_value_str) + return options_list + return [] + + if (static_options := super().options) is not None: + options_list = list(static_options) + if (current_value := self.native_value) is not None: + current_value_str = str(current_value) + if current_value_str not in options_list: + options_list.append(current_value_str) + return options_list + + return None diff --git a/homeassistant/components/smartthings/strings.json b/homeassistant/components/smartthings/strings.json index be0ffa053905b..1aa36e103bd32 100644 --- a/homeassistant/components/smartthings/strings.json +++ b/homeassistant/components/smartthings/strings.json @@ -970,7 +970,7 @@ "66": "Denim", "2e": "Baby Care", "2d": "Silent Wash", - "30": "Cloudy Day", + "30": "Cloudy day", "29": "Drum Clean+", "27": "Rinse+Spin", "28": "Drain/Spin" From 22f9d4da349a9553f2294b1341ae446aa0273162 Mon Sep 17 00:00:00 2001 From: gielk Date: Thu, 21 May 2026 22:07:24 +0200 Subject: [PATCH 4/7] refactor(smartthings): align washer and dryer sensors with dishwasher capability pattern --- .../components/smartthings/sensor.py | 46 +- .../components/smartthings/strings.json | 126 +- .../smartthings/snapshots/test_sensor.ambr | 2143 +++++++++++++---- 3 files changed, 1782 insertions(+), 533 deletions(-) diff --git a/homeassistant/components/smartthings/sensor.py b/homeassistant/components/smartthings/sensor.py index d98e1cb5d283e..a5e38c5076613 100644 --- a/homeassistant/components/smartthings/sensor.py +++ b/homeassistant/components/smartthings/sensor.py @@ -193,7 +193,6 @@ ] - def power_attributes(status: dict[str, Any]) -> dict[str, Any]: """Return the power attributes.""" state = {} @@ -208,7 +207,11 @@ def _normalize_cycle_value(value: Any) -> str | None: if not value: return None value_str = str(value) - return value_str.split("_")[-1].lower() if "_" in value_str else value_str.lower() + return ( + value_str.rsplit("_", maxsplit=1)[-1].lower() + if "_" in value_str + else value_str.lower() + ) @dataclass(frozen=True, kw_only=True) @@ -1213,7 +1216,6 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription): translation_key="washer_machine_state", options=WASHER_OPTIONS, device_class=SensorDeviceClass.ENUM, - component_fn=lambda component: component == "sub", component_translation_key={ "sub": "washer_sub_machine_state", }, @@ -1243,7 +1245,6 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription): ], device_class=SensorDeviceClass.ENUM, value_fn=lambda value: JOB_STATE_MAP.get(value, value), - component_fn=lambda component: component == "sub", component_translation_key={ "sub": "washer_sub_job_state", }, @@ -1255,7 +1256,6 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription): translation_key="completion_time", device_class=SensorDeviceClass.TIMESTAMP, value_fn=lambda value: dt_util.parse_datetime(value) if value else None, - component_fn=lambda component: component == "sub", component_translation_key={ "sub": "washer_sub_completion_time", }, @@ -1336,10 +1336,10 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription): ) ] }, - "samsungce.washerCycle": { - "washerCycle": [ + Capability.SAMSUNG_CE_WASHER_CYCLE: { + Attribute.WASHER_CYCLE: [ SmartThingsSensorEntityDescription( - key="washerCycle", + key=Attribute.WASHER_CYCLE, translation_key="washer_cycle", icon="mdi:washing-machine", options=WASHER_CYCLES, @@ -1349,10 +1349,10 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription): ) ] }, - "samsungce.dryerCycle": { - "dryerCycle": [ + Capability.SAMSUNG_CE_DRYER_CYCLE: { + Attribute.DRYER_CYCLE: [ SmartThingsSensorEntityDescription( - key="dryerCycle", + key=Attribute.DRYER_CYCLE, translation_key="dryer_cycle", icon="mdi:tumble-dryer", options=DRYER_CYCLES, @@ -1362,47 +1362,47 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription): ) ] }, - "samsungce.washerOperatingState": { - "progress": [ + Capability.SAMSUNG_CE_WASHER_OPERATING_STATE: { + Attribute.PROGRESS: [ SmartThingsSensorEntityDescription( - key="progress", + key=Attribute.PROGRESS, translation_key="washer_progress", icon="mdi:washing-machine", state_class=SensorStateClass.MEASUREMENT, native_unit_of_measurement=PERCENTAGE, ) ], - "remainingTime": [ + Attribute.REMAINING_TIME: [ SmartThingsSensorEntityDescription( - key="remainingTime", + key=Attribute.REMAINING_TIME, translation_key="washer_remaining_time", icon="mdi:timer-sand", state_class=SensorStateClass.MEASUREMENT, device_class=SensorDeviceClass.DURATION, native_unit_of_measurement=UnitOfTime.MINUTES, ) - ] + ], }, - "samsungce.dryerOperatingState": { - "progress": [ + Capability.SAMSUNG_CE_DRYER_OPERATING_STATE: { + Attribute.PROGRESS: [ SmartThingsSensorEntityDescription( - key="progress", + key=Attribute.PROGRESS, translation_key="dryer_progress", icon="mdi:tumble-dryer", state_class=SensorStateClass.MEASUREMENT, native_unit_of_measurement=PERCENTAGE, ) ], - "remainingTime": [ + Attribute.REMAINING_TIME: [ SmartThingsSensorEntityDescription( - key="remainingTime", + key=Attribute.REMAINING_TIME, translation_key="dryer_remaining_time", icon="mdi:timer-sand", state_class=SensorStateClass.MEASUREMENT, device_class=SensorDeviceClass.DURATION, native_unit_of_measurement=UnitOfTime.MINUTES, ) - ] + ], }, } diff --git a/homeassistant/components/smartthings/strings.json b/homeassistant/components/smartthings/strings.json index 1aa36e103bd32..bee5a4fa0ddad 100644 --- a/homeassistant/components/smartthings/strings.json +++ b/homeassistant/components/smartthings/strings.json @@ -505,6 +505,29 @@ "tank": "Tank" } }, + "dryer_cycle": { + "name": "Dryer cycle", + "state": { + "1a": "Wool", + "1b": "Bedding", + "1c": "Shirts", + "1d": "Towels", + "1e": "Outdoor", + "4c": "Air Refresh", + "4e": "Self Dry", + "17": "Super Speed", + "18": "Synthetics", + "19": "Delicates", + "20": "Iron Dry", + "21": "Hygiene Care", + "23": "Quick Dry 35'", + "24": "Cool Air", + "25": "Warm Air", + "27": "Time Dry", + "51": "Eco Cotton", + "53": "AI Dry+" + } + }, "dryer_job_state": { "name": "[%key:component::smartthings::entity::sensor::dishwasher_job_state::name%]", "state": { @@ -529,13 +552,22 @@ "name": "[%key:component::smartthings::entity::sensor::dishwasher_machine_state::name%]", "state": { "pause": "[%key:common::state::paused%]", + "paused": "[%key:common::state::paused%]", + "ready": "[%key:component::smartthings::entity::sensor::oven_machine_state::state::ready%]", "run": "[%key:component::smartthings::entity::sensor::dishwasher_machine_state::state::run%]", + "running": "[%key:component::smartthings::entity::sensor::dishwasher_machine_state::state::run%]", "stop": "[%key:common::state::stopped%]" } }, "dryer_mode": { "name": "Dryer mode" }, + "dryer_progress": { + "name": "Drying progress" + }, + "dryer_remaining_time": { + "name": "Dryer remaining time" + }, "energy_difference": { "name": "Energy difference" }, @@ -918,6 +950,35 @@ "uv_index": { "name": "UV index" }, + "washer_cycle": { + "name": "Washer cycle", + "state": { + "1b": "Cotton", + "1c": "Eco 40-60", + "1d": "Super Speed", + "1e": "15' Quick Wash", + "2b": "AI Wash", + "2d": "Silent Wash", + "2e": "Baby Care", + "2f": "Activewear", + "8f": "Intense Cold", + "20": "Hygiene Steam", + "21": "Colors", + "22": "Wool", + "23": "Outdoor", + "24": "Bedding", + "25": "Synthetics", + "26": "Delicates", + "27": "Rinse+Spin", + "28": "Drain/Spin", + "29": "Drum Clean+", + "30": "Cloudy day", + "32": "Shirts", + "33": "Towels", + "66": "Denim", + "96": "Less Microfiber" + } + }, "washer_job_state": { "name": "[%key:component::smartthings::entity::sensor::dishwasher_job_state::name%]", "state": { @@ -943,77 +1004,22 @@ "name": "[%key:component::smartthings::entity::sensor::dishwasher_machine_state::name%]", "state": { "pause": "[%key:common::state::paused%]", + "paused": "[%key:common::state::paused%]", + "ready": "[%key:component::smartthings::entity::sensor::oven_machine_state::state::ready%]", "run": "[%key:component::smartthings::entity::sensor::dishwasher_machine_state::state::run%]", + "running": "[%key:component::smartthings::entity::sensor::dishwasher_machine_state::state::run%]", "stop": "[%key:common::state::stopped%]" } }, - "washer_cycle": { - "name": "Washer cycle", - "state": { - "1c": "Eco 40-60", - "2b": "AI Wash", - "1b": "Cotton", - "1e": "15' Quick Wash", - "1d": "Super Speed", - "96": "Less Microfiber", - "8f": "Intense Cold", - "25": "Synthetics", - "26": "Delicates", - "33": "Towels", - "24": "Bedding", - "32": "Shirts", - "20": "Hygiene Steam", - "22": "Wool", - "23": "Outdoor", - "2f": "Activewear", - "21": "Colors", - "66": "Denim", - "2e": "Baby Care", - "2d": "Silent Wash", - "30": "Cloudy day", - "29": "Drum Clean+", - "27": "Rinse+Spin", - "28": "Drain/Spin" - } - }, - "dryer_cycle": { - "name": "Dryer cycle", - "state": { - "51": "Eco Cotton", - "53": "AI Dry+", - "23": "Quick Dry 35'", - "17": "Super Speed", - "18": "Synthetics", - "19": "Delicates", - "1d": "Towels", - "1b": "Bedding", - "1c": "Shirts", - "21": "Hygiene Care", - "1a": "Wool", - "1e": "Outdoor", - "20": "Iron Dry", - "27": "Time Dry", - "25": "Warm Air", - "24": "Cool Air", - "4e": "Self Dry", - "4c": "Air Refresh" - } + "washer_mode": { + "name": "Washer mode" }, "washer_progress": { "name": "Washing progress" }, - "dryer_progress": { - "name": "Drying progress" - }, "washer_remaining_time": { "name": "Washer remaining time" }, - "dryer_remaining_time": { - "name": "Dryer remaining time" - }, - "washer_mode": { - "name": "Washer mode" - }, "washer_sub_completion_time": { "name": "Upper washer completion time" }, diff --git a/tests/components/smartthings/snapshots/test_sensor.ambr b/tests/components/smartthings/snapshots/test_sensor.ambr index f36a638ed3234..e493cd1568f66 100644 --- a/tests/components/smartthings/snapshots/test_sensor.ambr +++ b/tests/components/smartthings/snapshots/test_sensor.ambr @@ -15706,6 +15706,201 @@ 'state': '2025-02-08T19:25:10+00:00', }) # --- +# name: test_all_entities[da_wm_wd_000001][sensor.theater_dryer_dryer_cycle-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + '01', + '9c', + 'a5', + '9e', + '9b', + '27', + 'e5', + 'a0', + 'a4', + 'a6', + 'a3', + 'a2', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.theater_dryer_dryer_cycle', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Dryer cycle', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': 'mdi:tumble-dryer', + 'original_name': 'Dryer cycle', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'dryer_cycle', + 'unique_id': '02f7256e-8353-5bdd-547f-bd5b1647e01b_main_samsungce.dryerCycle_dryerCycle_dryerCycle', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[da_wm_wd_000001][sensor.theater_dryer_dryer_cycle-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Dryer Dryer cycle', + 'icon': 'mdi:tumble-dryer', + 'options': list([ + '01', + '9c', + 'a5', + '9e', + '9b', + '27', + 'e5', + 'a0', + 'a4', + 'a6', + 'a3', + 'a2', + ]), + }), + 'context': , + 'entity_id': 'sensor.theater_dryer_dryer_cycle', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '01', + }) +# --- +# name: test_all_entities[da_wm_wd_000001][sensor.theater_dryer_dryer_remaining_time-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.theater_dryer_dryer_remaining_time', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Dryer remaining time', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 2, + }), + }), + 'original_device_class': , + 'original_icon': 'mdi:timer-sand', + 'original_name': 'Dryer remaining time', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'dryer_remaining_time', + 'unique_id': '02f7256e-8353-5bdd-547f-bd5b1647e01b_main_samsungce.dryerOperatingState_remainingTime_remainingTime', + 'unit_of_measurement': 'min', + }) +# --- +# name: test_all_entities[da_wm_wd_000001][sensor.theater_dryer_dryer_remaining_time-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'duration', + 'friendly_name': 'Dryer Dryer remaining time', + 'icon': 'mdi:timer-sand', + 'state_class': , + 'unit_of_measurement': 'min', + }), + 'context': , + 'entity_id': 'sensor.theater_dryer_dryer_remaining_time', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '75', + }) +# --- +# name: test_all_entities[da_wm_wd_000001][sensor.theater_dryer_drying_progress-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.theater_dryer_drying_progress', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Drying progress', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:tumble-dryer', + 'original_name': 'Drying progress', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'dryer_progress', + 'unique_id': '02f7256e-8353-5bdd-547f-bd5b1647e01b_main_samsungce.dryerOperatingState_progress_progress', + 'unit_of_measurement': '%', + }) +# --- +# name: test_all_entities[da_wm_wd_000001][sensor.theater_dryer_drying_progress-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Dryer Drying progress', + 'icon': 'mdi:tumble-dryer', + 'state_class': , + 'unit_of_measurement': '%', + }), + 'context': , + 'entity_id': 'sensor.theater_dryer_drying_progress', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '1', + }) +# --- # name: test_all_entities[da_wm_wd_000001][sensor.theater_dryer_energy-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ @@ -16197,14 +16392,29 @@ 'state': '2025-03-09T22:55:37+00:00', }) # --- -# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_energy-entry] +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_dryer_cycle-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + 'options': list([ + '9a', + 'ca', + 'db', + '99', + '93', + 'b5', + 'd7', + 'a5', + '96', + '97', + '7f', + '98', + 'eb', + 'b6', + ]), }), 'config_entry_id': , 'config_subentry_id': , @@ -16213,7 +16423,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.seca_roupa_energy', + 'entity_id': 'sensor.seca_roupa_dryer_cycle', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -16221,48 +16431,60 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Energy', + 'object_id_base': 'Dryer cycle', 'options': dict({ - 'sensor': dict({ - 'suggested_display_precision': 2, - }), }), - 'original_device_class': , - 'original_icon': None, - 'original_name': 'Energy', + 'original_device_class': , + 'original_icon': 'mdi:tumble-dryer', + 'original_name': 'Dryer cycle', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': None, - 'unique_id': '3a6c4e05-811d-5041-e956-3d04c424cbcd_main_powerConsumptionReport_powerConsumption_energy_meter', - 'unit_of_measurement': , + 'translation_key': 'dryer_cycle', + 'unique_id': '3a6c4e05-811d-5041-e956-3d04c424cbcd_main_samsungce.dryerCycle_dryerCycle_dryerCycle', + 'unit_of_measurement': None, }) # --- -# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_energy-state] +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_dryer_cycle-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'device_class': 'energy', - 'friendly_name': 'Seca-Roupa Energy', - 'state_class': , - 'unit_of_measurement': , + 'device_class': 'enum', + 'friendly_name': 'Seca-Roupa Dryer cycle', + 'icon': 'mdi:tumble-dryer', + 'options': list([ + '9a', + 'ca', + 'db', + '99', + '93', + 'b5', + 'd7', + 'a5', + '96', + '97', + '7f', + '98', + 'eb', + 'b6', + ]), }), 'context': , - 'entity_id': 'sensor.seca_roupa_energy', + 'entity_id': 'sensor.seca_roupa_dryer_cycle', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': '796.4', + 'state': '9a', }) # --- -# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_energy_difference-entry] +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_dryer_remaining_time-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + 'state_class': , }), 'config_entry_id': , 'config_subentry_id': , @@ -16271,7 +16493,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.seca_roupa_energy_difference', + 'entity_id': 'sensor.seca_roupa_dryer_remaining_time', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -16279,48 +16501,49 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Energy difference', + 'object_id_base': 'Dryer remaining time', 'options': dict({ 'sensor': dict({ 'suggested_display_precision': 2, }), }), - 'original_device_class': , - 'original_icon': None, - 'original_name': 'Energy difference', + 'original_device_class': , + 'original_icon': 'mdi:timer-sand', + 'original_name': 'Dryer remaining time', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': 'energy_difference', - 'unique_id': '3a6c4e05-811d-5041-e956-3d04c424cbcd_main_powerConsumptionReport_powerConsumption_deltaEnergy_meter', - 'unit_of_measurement': , + 'translation_key': 'dryer_remaining_time', + 'unique_id': '3a6c4e05-811d-5041-e956-3d04c424cbcd_main_samsungce.dryerOperatingState_remainingTime_remainingTime', + 'unit_of_measurement': 'min', }) # --- -# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_energy_difference-state] +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_dryer_remaining_time-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'device_class': 'energy', - 'friendly_name': 'Seca-Roupa Energy difference', - 'state_class': , - 'unit_of_measurement': , + 'device_class': 'duration', + 'friendly_name': 'Seca-Roupa Dryer remaining time', + 'icon': 'mdi:timer-sand', + 'state_class': , + 'unit_of_measurement': 'min', }), 'context': , - 'entity_id': 'sensor.seca_roupa_energy_difference', + 'entity_id': 'sensor.seca_roupa_dryer_remaining_time', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': '0.0', + 'state': '188', }) # --- -# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_energy_saved-entry] +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_drying_progress-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + 'state_class': , }), 'config_entry_id': , 'config_subentry_id': , @@ -16329,7 +16552,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.seca_roupa_energy_saved', + 'entity_id': 'sensor.seca_roupa_drying_progress', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -16337,64 +16560,45 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Energy saved', + 'object_id_base': 'Drying progress', 'options': dict({ - 'sensor': dict({ - 'suggested_display_precision': 2, - }), }), - 'original_device_class': , - 'original_icon': None, - 'original_name': 'Energy saved', + 'original_device_class': None, + 'original_icon': 'mdi:tumble-dryer', + 'original_name': 'Drying progress', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': 'energy_saved', - 'unique_id': '3a6c4e05-811d-5041-e956-3d04c424cbcd_main_powerConsumptionReport_powerConsumption_energySaved_meter', - 'unit_of_measurement': , + 'translation_key': 'dryer_progress', + 'unique_id': '3a6c4e05-811d-5041-e956-3d04c424cbcd_main_samsungce.dryerOperatingState_progress_progress', + 'unit_of_measurement': '%', }) # --- -# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_energy_saved-state] +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_drying_progress-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'device_class': 'energy', - 'friendly_name': 'Seca-Roupa Energy saved', - 'state_class': , - 'unit_of_measurement': , + 'friendly_name': 'Seca-Roupa Drying progress', + 'icon': 'mdi:tumble-dryer', + 'state_class': , + 'unit_of_measurement': '%', }), 'context': , - 'entity_id': 'sensor.seca_roupa_energy_saved', + 'entity_id': 'sensor.seca_roupa_drying_progress', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': '0.0', + 'state': '1', }) # --- -# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_job_state-entry] +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_energy-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, ]), 'area_id': None, 'capabilities': dict({ - 'options': list([ - 'cooling', - 'delay_wash', - 'drying', - 'finished', - 'none', - 'refreshing', - 'weight_sensing', - 'wrinkle_prevent', - 'dehumidifying', - 'ai_drying', - 'sanitizing', - 'internal_care', - 'freeze_protection', - 'continuous_dehumidifying', - 'thawing_frozen_inside', - ]), + 'state_class': , }), 'config_entry_id': , 'config_subentry_id': , @@ -16403,7 +16607,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.seca_roupa_job_state', + 'entity_id': 'sensor.seca_roupa_energy', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -16411,37 +16615,227 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Job state', + 'object_id_base': 'Energy', 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 2, + }), }), - 'original_device_class': , + 'original_device_class': , 'original_icon': None, - 'original_name': 'Job state', + 'original_name': 'Energy', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': 'dryer_job_state', - 'unique_id': '3a6c4e05-811d-5041-e956-3d04c424cbcd_main_dryerOperatingState_dryerJobState_dryerJobState', - 'unit_of_measurement': None, + 'translation_key': None, + 'unique_id': '3a6c4e05-811d-5041-e956-3d04c424cbcd_main_powerConsumptionReport_powerConsumption_energy_meter', + 'unit_of_measurement': , }) # --- -# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_job_state-state] +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_energy-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'device_class': 'enum', - 'friendly_name': 'Seca-Roupa Job state', - 'options': list([ - 'cooling', - 'delay_wash', - 'drying', - 'finished', - 'none', - 'refreshing', - 'weight_sensing', - 'wrinkle_prevent', - 'dehumidifying', - 'ai_drying', + 'device_class': 'energy', + 'friendly_name': 'Seca-Roupa Energy', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.seca_roupa_energy', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '796.4', + }) +# --- +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_energy_difference-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.seca_roupa_energy_difference', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Energy difference', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 2, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Energy difference', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'energy_difference', + 'unique_id': '3a6c4e05-811d-5041-e956-3d04c424cbcd_main_powerConsumptionReport_powerConsumption_deltaEnergy_meter', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_energy_difference-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'energy', + 'friendly_name': 'Seca-Roupa Energy difference', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.seca_roupa_energy_difference', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '0.0', + }) +# --- +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_energy_saved-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.seca_roupa_energy_saved', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Energy saved', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 2, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Energy saved', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'energy_saved', + 'unique_id': '3a6c4e05-811d-5041-e956-3d04c424cbcd_main_powerConsumptionReport_powerConsumption_energySaved_meter', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_energy_saved-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'energy', + 'friendly_name': 'Seca-Roupa Energy saved', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.seca_roupa_energy_saved', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '0.0', + }) +# --- +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_job_state-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'cooling', + 'delay_wash', + 'drying', + 'finished', + 'none', + 'refreshing', + 'weight_sensing', + 'wrinkle_prevent', + 'dehumidifying', + 'ai_drying', + 'sanitizing', + 'internal_care', + 'freeze_protection', + 'continuous_dehumidifying', + 'thawing_frozen_inside', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.seca_roupa_job_state', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Job state', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Job state', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'dryer_job_state', + 'unique_id': '3a6c4e05-811d-5041-e956-3d04c424cbcd_main_dryerOperatingState_dryerJobState_dryerJobState', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_job_state-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Seca-Roupa Job state', + 'options': list([ + 'cooling', + 'delay_wash', + 'drying', + 'finished', + 'none', + 'refreshing', + 'weight_sensing', + 'wrinkle_prevent', + 'dehumidifying', + 'ai_drying', 'sanitizing', 'internal_care', 'freeze_protection', @@ -16556,37 +16950,241 @@ 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': None, - 'unique_id': '3a6c4e05-811d-5041-e956-3d04c424cbcd_main_powerConsumptionReport_powerConsumption_power_meter', - 'unit_of_measurement': , + 'translation_key': None, + 'unique_id': '3a6c4e05-811d-5041-e956-3d04c424cbcd_main_powerConsumptionReport_powerConsumption_power_meter', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_power-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'power', + 'friendly_name': 'Seca-Roupa Power', + 'power_consumption_end': '2025-03-09T19:47:37Z', + 'power_consumption_start': '2025-03-09T19:47:26Z', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.seca_roupa_power', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '0', + }) +# --- +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_power_energy-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.seca_roupa_power_energy', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Power energy', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 2, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Power energy', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'power_energy', + 'unique_id': '3a6c4e05-811d-5041-e956-3d04c424cbcd_main_powerConsumptionReport_powerConsumption_powerEnergy_meter', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_power_energy-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'energy', + 'friendly_name': 'Seca-Roupa Power energy', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.seca_roupa_power_energy', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '0.0', + }) +# --- +# name: test_all_entities[da_wm_wd_01011][sensor.trockner_completion_time-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.trockner_completion_time', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Completion time', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Completion time', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'completion_time', + 'unique_id': '3d39866c-7716-5259-44f0-fd7025efd85f_main_dryerOperatingState_completionTime_completionTime', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[da_wm_wd_01011][sensor.trockner_completion_time-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'timestamp', + 'friendly_name': 'Trockner Completion time', + }), + 'context': , + 'entity_id': 'sensor.trockner_completion_time', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2025-10-16T14:15:07+00:00', + }) +# --- +# name: test_all_entities[da_wm_wd_01011][sensor.trockner_dryer_cycle-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + '51', + '53', + '23', + '17', + '18', + '19', + '1d', + '1b', + '1c', + '21', + '1a', + '1e', + '22', + '20', + '27', + '25', + '24', + '4e', + '4c', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.trockner_dryer_cycle', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Dryer cycle', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': 'mdi:tumble-dryer', + 'original_name': 'Dryer cycle', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'dryer_cycle', + 'unique_id': '3d39866c-7716-5259-44f0-fd7025efd85f_main_samsungce.dryerCycle_dryerCycle_dryerCycle', + 'unit_of_measurement': None, }) # --- -# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_power-state] +# name: test_all_entities[da_wm_wd_01011][sensor.trockner_dryer_cycle-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'device_class': 'power', - 'friendly_name': 'Seca-Roupa Power', - 'power_consumption_end': '2025-03-09T19:47:37Z', - 'power_consumption_start': '2025-03-09T19:47:26Z', - 'state_class': , - 'unit_of_measurement': , + 'device_class': 'enum', + 'friendly_name': 'Trockner Dryer cycle', + 'icon': 'mdi:tumble-dryer', + 'options': list([ + '51', + '53', + '23', + '17', + '18', + '19', + '1d', + '1b', + '1c', + '21', + '1a', + '1e', + '22', + '20', + '27', + '25', + '24', + '4e', + '4c', + ]), }), 'context': , - 'entity_id': 'sensor.seca_roupa_power', + 'entity_id': 'sensor.trockner_dryer_cycle', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': '0', + 'state': '51', }) # --- -# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_power_energy-entry] +# name: test_all_entities[da_wm_wd_01011][sensor.trockner_dryer_remaining_time-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + 'state_class': , }), 'config_entry_id': , 'config_subentry_id': , @@ -16595,7 +17193,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.seca_roupa_power_energy', + 'entity_id': 'sensor.trockner_dryer_remaining_time', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -16603,47 +17201,50 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Power energy', + 'object_id_base': 'Dryer remaining time', 'options': dict({ 'sensor': dict({ 'suggested_display_precision': 2, }), }), - 'original_device_class': , - 'original_icon': None, - 'original_name': 'Power energy', + 'original_device_class': , + 'original_icon': 'mdi:timer-sand', + 'original_name': 'Dryer remaining time', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': 'power_energy', - 'unique_id': '3a6c4e05-811d-5041-e956-3d04c424cbcd_main_powerConsumptionReport_powerConsumption_powerEnergy_meter', - 'unit_of_measurement': , + 'translation_key': 'dryer_remaining_time', + 'unique_id': '3d39866c-7716-5259-44f0-fd7025efd85f_main_samsungce.dryerOperatingState_remainingTime_remainingTime', + 'unit_of_measurement': 'min', }) # --- -# name: test_all_entities[da_wm_wd_000001_1][sensor.seca_roupa_power_energy-state] +# name: test_all_entities[da_wm_wd_01011][sensor.trockner_dryer_remaining_time-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'device_class': 'energy', - 'friendly_name': 'Seca-Roupa Power energy', - 'state_class': , - 'unit_of_measurement': , + 'device_class': 'duration', + 'friendly_name': 'Trockner Dryer remaining time', + 'icon': 'mdi:timer-sand', + 'state_class': , + 'unit_of_measurement': 'min', }), 'context': , - 'entity_id': 'sensor.seca_roupa_power_energy', + 'entity_id': 'sensor.trockner_dryer_remaining_time', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': '0.0', + 'state': '270', }) # --- -# name: test_all_entities[da_wm_wd_01011][sensor.trockner_completion_time-entry] +# name: test_all_entities[da_wm_wd_01011][sensor.trockner_drying_progress-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, ]), 'area_id': None, - 'capabilities': None, + 'capabilities': dict({ + 'state_class': , + }), 'config_entry_id': , 'config_subentry_id': , 'device_class': None, @@ -16651,7 +17252,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.trockner_completion_time', + 'entity_id': 'sensor.trockner_drying_progress', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -16659,33 +17260,35 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Completion time', + 'object_id_base': 'Drying progress', 'options': dict({ }), - 'original_device_class': , - 'original_icon': None, - 'original_name': 'Completion time', + 'original_device_class': None, + 'original_icon': 'mdi:tumble-dryer', + 'original_name': 'Drying progress', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': 'completion_time', - 'unique_id': '3d39866c-7716-5259-44f0-fd7025efd85f_main_dryerOperatingState_completionTime_completionTime', - 'unit_of_measurement': None, + 'translation_key': 'dryer_progress', + 'unique_id': '3d39866c-7716-5259-44f0-fd7025efd85f_main_samsungce.dryerOperatingState_progress_progress', + 'unit_of_measurement': '%', }) # --- -# name: test_all_entities[da_wm_wd_01011][sensor.trockner_completion_time-state] +# name: test_all_entities[da_wm_wd_01011][sensor.trockner_drying_progress-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'device_class': 'timestamp', - 'friendly_name': 'Trockner Completion time', + 'friendly_name': 'Trockner Drying progress', + 'icon': 'mdi:tumble-dryer', + 'state_class': , + 'unit_of_measurement': '%', }), 'context': , - 'entity_id': 'sensor.trockner_completion_time', + 'entity_id': 'sensor.trockner_drying_progress', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': '2025-10-16T14:15:07+00:00', + 'state': '1', }) # --- # name: test_all_entities[da_wm_wd_01011][sensor.trockner_energy-entry] @@ -17412,36 +18015,216 @@ # name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_job_state-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'device_class': 'enum', - 'friendly_name': 'Washer Job state', - 'options': list([ - 'air_wash', - 'ai_rinse', - 'ai_spin', - 'ai_wash', - 'cooling', - 'delay_wash', - 'drying', - 'finish', - 'none', - 'pre_wash', - 'rinse', - 'spin', - 'wash', - 'weight_sensing', - 'wrinkle_prevent', - 'freeze_protection', - ]), + 'device_class': 'enum', + 'friendly_name': 'Washer Job state', + 'options': list([ + 'air_wash', + 'ai_rinse', + 'ai_spin', + 'ai_wash', + 'cooling', + 'delay_wash', + 'drying', + 'finish', + 'none', + 'pre_wash', + 'rinse', + 'spin', + 'wash', + 'weight_sensing', + 'wrinkle_prevent', + 'freeze_protection', + ]), + }), + 'context': , + 'entity_id': 'sensor.theater_washer_job_state', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'none', + }) +# --- +# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_machine_state-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'pause', + 'run', + 'stop', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.theater_washer_machine_state', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Machine state', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Machine state', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'washer_machine_state', + 'unique_id': 'f984b91d-f250-9d42-3436-33f09a422a47_main_washerOperatingState_machineState_machineState', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_machine_state-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Washer Machine state', + 'options': list([ + 'pause', + 'run', + 'stop', + ]), + }), + 'context': , + 'entity_id': 'sensor.theater_washer_machine_state', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'stop', + }) +# --- +# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_power-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.theater_washer_power', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Power', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 2, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Power', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'f984b91d-f250-9d42-3436-33f09a422a47_main_powerConsumptionReport_powerConsumption_power_meter', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_power-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'power', + 'friendly_name': 'Washer Power', + 'power_consumption_end': '2025-02-07T03:09:45Z', + 'power_consumption_start': '2025-02-07T03:09:24Z', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.theater_washer_power', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '0', + }) +# --- +# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_power_energy-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.theater_washer_power_energy', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Power energy', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 2, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Power energy', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'power_energy', + 'unique_id': 'f984b91d-f250-9d42-3436-33f09a422a47_main_powerConsumptionReport_powerConsumption_powerEnergy_meter', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_power_energy-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'energy', + 'friendly_name': 'Washer Power energy', + 'state_class': , + 'unit_of_measurement': , }), 'context': , - 'entity_id': 'sensor.theater_washer_job_state', + 'entity_id': 'sensor.theater_washer_power_energy', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'none', + 'state': '0.0', }) # --- -# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_machine_state-entry] +# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_washer_cycle-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, @@ -17449,9 +18232,18 @@ 'area_id': None, 'capabilities': dict({ 'options': list([ - 'pause', - 'run', - 'stop', + '01', + '70', + '55', + '71', + '72', + '77', + 'e5', + '57', + '73', + '74', + '75', + '78', ]), }), 'config_entry_id': , @@ -17461,7 +18253,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.theater_washer_machine_state', + 'entity_id': 'sensor.theater_washer_washer_cycle', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -17469,41 +18261,51 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Machine state', + 'object_id_base': 'Washer cycle', 'options': dict({ }), 'original_device_class': , - 'original_icon': None, - 'original_name': 'Machine state', + 'original_icon': 'mdi:washing-machine', + 'original_name': 'Washer cycle', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': 'washer_machine_state', - 'unique_id': 'f984b91d-f250-9d42-3436-33f09a422a47_main_washerOperatingState_machineState_machineState', + 'translation_key': 'washer_cycle', + 'unique_id': 'f984b91d-f250-9d42-3436-33f09a422a47_main_samsungce.washerCycle_washerCycle_washerCycle', 'unit_of_measurement': None, }) # --- -# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_machine_state-state] +# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_washer_cycle-state] StateSnapshot({ 'attributes': ReadOnlyDict({ 'device_class': 'enum', - 'friendly_name': 'Washer Machine state', + 'friendly_name': 'Washer Washer cycle', + 'icon': 'mdi:washing-machine', 'options': list([ - 'pause', - 'run', - 'stop', + '01', + '70', + '55', + '71', + '72', + '77', + 'e5', + '57', + '73', + '74', + '75', + '78', ]), }), 'context': , - 'entity_id': 'sensor.theater_washer_machine_state', + 'entity_id': 'sensor.theater_washer_washer_cycle', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'stop', + 'state': '01', }) # --- -# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_power-entry] +# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_washer_remaining_time-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, @@ -17519,7 +18321,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.theater_washer_power', + 'entity_id': 'sensor.theater_washer_washer_remaining_time', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -17527,50 +18329,49 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Power', + 'object_id_base': 'Washer remaining time', 'options': dict({ 'sensor': dict({ 'suggested_display_precision': 2, }), }), - 'original_device_class': , - 'original_icon': None, - 'original_name': 'Power', + 'original_device_class': , + 'original_icon': 'mdi:timer-sand', + 'original_name': 'Washer remaining time', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': None, - 'unique_id': 'f984b91d-f250-9d42-3436-33f09a422a47_main_powerConsumptionReport_powerConsumption_power_meter', - 'unit_of_measurement': , + 'translation_key': 'washer_remaining_time', + 'unique_id': 'f984b91d-f250-9d42-3436-33f09a422a47_main_samsungce.washerOperatingState_remainingTime_remainingTime', + 'unit_of_measurement': 'min', }) # --- -# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_power-state] +# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_washer_remaining_time-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'device_class': 'power', - 'friendly_name': 'Washer Power', - 'power_consumption_end': '2025-02-07T03:09:45Z', - 'power_consumption_start': '2025-02-07T03:09:24Z', + 'device_class': 'duration', + 'friendly_name': 'Washer Washer remaining time', + 'icon': 'mdi:timer-sand', 'state_class': , - 'unit_of_measurement': , + 'unit_of_measurement': 'min', }), 'context': , - 'entity_id': 'sensor.theater_washer_power', + 'entity_id': 'sensor.theater_washer_washer_remaining_time', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': '0', + 'state': '45', }) # --- -# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_power_energy-entry] +# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_washing_progress-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + 'state_class': , }), 'config_entry_id': , 'config_subentry_id': , @@ -17579,7 +18380,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.theater_washer_power_energy', + 'entity_id': 'sensor.theater_washer_washing_progress', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -17587,38 +18388,35 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Power energy', + 'object_id_base': 'Washing progress', 'options': dict({ - 'sensor': dict({ - 'suggested_display_precision': 2, - }), }), - 'original_device_class': , - 'original_icon': None, - 'original_name': 'Power energy', + 'original_device_class': None, + 'original_icon': 'mdi:washing-machine', + 'original_name': 'Washing progress', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': 'power_energy', - 'unique_id': 'f984b91d-f250-9d42-3436-33f09a422a47_main_powerConsumptionReport_powerConsumption_powerEnergy_meter', - 'unit_of_measurement': , + 'translation_key': 'washer_progress', + 'unique_id': 'f984b91d-f250-9d42-3436-33f09a422a47_main_samsungce.washerOperatingState_progress_progress', + 'unit_of_measurement': '%', }) # --- -# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_power_energy-state] +# name: test_all_entities[da_wm_wm_000001][sensor.theater_washer_washing_progress-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'device_class': 'energy', - 'friendly_name': 'Washer Power energy', - 'state_class': , - 'unit_of_measurement': , + 'friendly_name': 'Washer Washing progress', + 'icon': 'mdi:washing-machine', + 'state_class': , + 'unit_of_measurement': '%', }), 'context': , - 'entity_id': 'sensor.theater_washer_power_energy', + 'entity_id': 'sensor.theater_washer_washing_progress', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': '0.0', + 'state': '1', }) # --- # name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_completion_time-entry] @@ -17927,14 +18725,194 @@ ]), }), 'context': , - 'entity_id': 'sensor.washing_machine_job_state', + 'entity_id': 'sensor.washing_machine_job_state', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'wash', + }) +# --- +# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_machine_state-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'pause', + 'run', + 'stop', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.washing_machine_machine_state', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Machine state', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Machine state', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'washer_machine_state', + 'unique_id': '63803fae-cbed-f356-a063-2cf148ae3ca7_main_washerOperatingState_machineState_machineState', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_machine_state-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Washing Machine Machine state', + 'options': list([ + 'pause', + 'run', + 'stop', + ]), + }), + 'context': , + 'entity_id': 'sensor.washing_machine_machine_state', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'run', + }) +# --- +# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_power-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.washing_machine_power', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Power', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 2, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Power', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '63803fae-cbed-f356-a063-2cf148ae3ca7_main_powerConsumptionReport_powerConsumption_power_meter', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_power-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'power', + 'friendly_name': 'Washing Machine Power', + 'power_consumption_end': '2025-03-07T06:23:21Z', + 'power_consumption_start': '2025-03-07T06:21:09Z', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.washing_machine_power', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '0', + }) +# --- +# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_power_energy-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.washing_machine_power_energy', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Power energy', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 2, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Power energy', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'power_energy', + 'unique_id': '63803fae-cbed-f356-a063-2cf148ae3ca7_main_powerConsumptionReport_powerConsumption_powerEnergy_meter', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_power_energy-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'energy', + 'friendly_name': 'Washing Machine Power energy', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.washing_machine_power_energy', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'wash', + 'state': '0.0', }) # --- -# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_machine_state-entry] +# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_washer_cycle-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, @@ -17942,9 +18920,20 @@ 'area_id': None, 'capabilities': dict({ 'options': list([ - 'pause', - 'run', - 'stop', + 'd0', + 'dc', + 'e3', + 'e4', + '50', + '51', + 'ca', + 'e7', + 'c7', + 'd8', + 'd4', + 'd3', + 'da', + 'd2', ]), }), 'config_entry_id': , @@ -17954,7 +18943,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.washing_machine_machine_state', + 'entity_id': 'sensor.washing_machine_washer_cycle', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -17962,41 +18951,53 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Machine state', + 'object_id_base': 'Washer cycle', 'options': dict({ }), 'original_device_class': , - 'original_icon': None, - 'original_name': 'Machine state', + 'original_icon': 'mdi:washing-machine', + 'original_name': 'Washer cycle', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': 'washer_machine_state', - 'unique_id': '63803fae-cbed-f356-a063-2cf148ae3ca7_main_washerOperatingState_machineState_machineState', + 'translation_key': 'washer_cycle', + 'unique_id': '63803fae-cbed-f356-a063-2cf148ae3ca7_main_samsungce.washerCycle_washerCycle_washerCycle', 'unit_of_measurement': None, }) # --- -# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_machine_state-state] +# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_washer_cycle-state] StateSnapshot({ 'attributes': ReadOnlyDict({ 'device_class': 'enum', - 'friendly_name': 'Washing Machine Machine state', + 'friendly_name': 'Washing Machine Washer cycle', + 'icon': 'mdi:washing-machine', 'options': list([ - 'pause', - 'run', - 'stop', + 'd0', + 'dc', + 'e3', + 'e4', + '50', + '51', + 'ca', + 'e7', + 'c7', + 'd8', + 'd4', + 'd3', + 'da', + 'd2', ]), }), 'context': , - 'entity_id': 'sensor.washing_machine_machine_state', + 'entity_id': 'sensor.washing_machine_washer_cycle', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'run', + 'state': 'e3', }) # --- -# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_power-entry] +# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_washer_remaining_time-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, @@ -18012,7 +19013,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.washing_machine_power', + 'entity_id': 'sensor.washing_machine_washer_remaining_time', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -18020,50 +19021,49 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Power', + 'object_id_base': 'Washer remaining time', 'options': dict({ 'sensor': dict({ 'suggested_display_precision': 2, }), }), - 'original_device_class': , - 'original_icon': None, - 'original_name': 'Power', + 'original_device_class': , + 'original_icon': 'mdi:timer-sand', + 'original_name': 'Washer remaining time', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': None, - 'unique_id': '63803fae-cbed-f356-a063-2cf148ae3ca7_main_powerConsumptionReport_powerConsumption_power_meter', - 'unit_of_measurement': , + 'translation_key': 'washer_remaining_time', + 'unique_id': '63803fae-cbed-f356-a063-2cf148ae3ca7_main_samsungce.washerOperatingState_remainingTime_remainingTime', + 'unit_of_measurement': 'min', }) # --- -# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_power-state] +# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_washer_remaining_time-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'device_class': 'power', - 'friendly_name': 'Washing Machine Power', - 'power_consumption_end': '2025-03-07T06:23:21Z', - 'power_consumption_start': '2025-03-07T06:21:09Z', + 'device_class': 'duration', + 'friendly_name': 'Washing Machine Washer remaining time', + 'icon': 'mdi:timer-sand', 'state_class': , - 'unit_of_measurement': , + 'unit_of_measurement': 'min', }), 'context': , - 'entity_id': 'sensor.washing_machine_power', + 'entity_id': 'sensor.washing_machine_washer_remaining_time', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': '0', + 'state': '31', }) # --- -# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_power_energy-entry] +# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_washing_progress-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + 'state_class': , }), 'config_entry_id': , 'config_subentry_id': , @@ -18072,7 +19072,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.washing_machine_power_energy', + 'entity_id': 'sensor.washing_machine_washing_progress', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -18080,38 +19080,35 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Power energy', + 'object_id_base': 'Washing progress', 'options': dict({ - 'sensor': dict({ - 'suggested_display_precision': 2, - }), }), - 'original_device_class': , - 'original_icon': None, - 'original_name': 'Power energy', + 'original_device_class': None, + 'original_icon': 'mdi:washing-machine', + 'original_name': 'Washing progress', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': 'power_energy', - 'unique_id': '63803fae-cbed-f356-a063-2cf148ae3ca7_main_powerConsumptionReport_powerConsumption_powerEnergy_meter', - 'unit_of_measurement': , + 'translation_key': 'washer_progress', + 'unique_id': '63803fae-cbed-f356-a063-2cf148ae3ca7_main_samsungce.washerOperatingState_progress_progress', + 'unit_of_measurement': '%', }) # --- -# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_power_energy-state] +# name: test_all_entities[da_wm_wm_000001_1][sensor.washing_machine_washing_progress-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'device_class': 'energy', - 'friendly_name': 'Washing Machine Power energy', - 'state_class': , - 'unit_of_measurement': , + 'friendly_name': 'Washing Machine Washing progress', + 'icon': 'mdi:washing-machine', + 'state_class': , + 'unit_of_measurement': '%', }), 'context': , - 'entity_id': 'sensor.washing_machine_power_energy', + 'entity_id': 'sensor.washing_machine_washing_progress', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': '0.0', + 'state': '36', }) # --- # name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_completion_time-entry] @@ -18435,9 +19432,210 @@ 'area_id': None, 'capabilities': dict({ 'options': list([ - 'pause', - 'run', - 'stop', + 'pause', + 'run', + 'stop', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.machine_a_laver_machine_state', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Machine state', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Machine state', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'washer_machine_state', + 'unique_id': 'b854ca5f-dc54-140d-6349-758b4d973c41_main_washerOperatingState_machineState_machineState', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_machine_state-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Machine à Laver Machine state', + 'options': list([ + 'pause', + 'run', + 'stop', + ]), + }), + 'context': , + 'entity_id': 'sensor.machine_a_laver_machine_state', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'run', + }) +# --- +# name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_power-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.machine_a_laver_power', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Power', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 2, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Power', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'b854ca5f-dc54-140d-6349-758b4d973c41_main_powerConsumptionReport_powerConsumption_power_meter', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_power-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'power', + 'friendly_name': 'Machine à Laver Power', + 'power_consumption_end': '2025-04-25T08:43:46Z', + 'power_consumption_start': '2025-04-25T08:28:43Z', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.machine_a_laver_power', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '0', + }) +# --- +# name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_power_energy-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.machine_a_laver_power_energy', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Power energy', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 2, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Power energy', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'power_energy', + 'unique_id': 'b854ca5f-dc54-140d-6349-758b4d973c41_main_powerConsumptionReport_powerConsumption_powerEnergy_meter', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_power_energy-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'energy', + 'friendly_name': 'Machine à Laver Power energy', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.machine_a_laver_power_energy', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '0.0', + }) +# --- +# name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_washer_cycle-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + '1c', + '2b', + '1b', + '1e', + '1d', + '96', + '8f', + '25', + '26', + '33', + '24', + '32', + '20', + '22', + '23', + '2f', + '21', + '2a', + '2e', + '2d', + '30', + '29', + '27', + '28', ]), }), 'config_entry_id': , @@ -18447,7 +19645,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.machine_a_laver_machine_state', + 'entity_id': 'sensor.machine_a_laver_washer_cycle', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -18455,41 +19653,63 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Machine state', + 'object_id_base': 'Washer cycle', 'options': dict({ }), 'original_device_class': , - 'original_icon': None, - 'original_name': 'Machine state', + 'original_icon': 'mdi:washing-machine', + 'original_name': 'Washer cycle', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': 'washer_machine_state', - 'unique_id': 'b854ca5f-dc54-140d-6349-758b4d973c41_main_washerOperatingState_machineState_machineState', + 'translation_key': 'washer_cycle', + 'unique_id': 'b854ca5f-dc54-140d-6349-758b4d973c41_main_samsungce.washerCycle_washerCycle_washerCycle', 'unit_of_measurement': None, }) # --- -# name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_machine_state-state] +# name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_washer_cycle-state] StateSnapshot({ 'attributes': ReadOnlyDict({ 'device_class': 'enum', - 'friendly_name': 'Machine à Laver Machine state', + 'friendly_name': 'Machine à Laver Washer cycle', + 'icon': 'mdi:washing-machine', 'options': list([ - 'pause', - 'run', - 'stop', + '1c', + '2b', + '1b', + '1e', + '1d', + '96', + '8f', + '25', + '26', + '33', + '24', + '32', + '20', + '22', + '23', + '2f', + '21', + '2a', + '2e', + '2d', + '30', + '29', + '27', + '28', ]), }), 'context': , - 'entity_id': 'sensor.machine_a_laver_machine_state', + 'entity_id': 'sensor.machine_a_laver_washer_cycle', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'run', + 'state': '1c', }) # --- -# name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_power-entry] +# name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_washer_remaining_time-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, @@ -18505,7 +19725,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.machine_a_laver_power', + 'entity_id': 'sensor.machine_a_laver_washer_remaining_time', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -18513,50 +19733,49 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Power', + 'object_id_base': 'Washer remaining time', 'options': dict({ 'sensor': dict({ 'suggested_display_precision': 2, }), }), - 'original_device_class': , - 'original_icon': None, - 'original_name': 'Power', + 'original_device_class': , + 'original_icon': 'mdi:timer-sand', + 'original_name': 'Washer remaining time', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': None, - 'unique_id': 'b854ca5f-dc54-140d-6349-758b4d973c41_main_powerConsumptionReport_powerConsumption_power_meter', - 'unit_of_measurement': , + 'translation_key': 'washer_remaining_time', + 'unique_id': 'b854ca5f-dc54-140d-6349-758b4d973c41_main_samsungce.washerOperatingState_remainingTime_remainingTime', + 'unit_of_measurement': 'min', }) # --- -# name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_power-state] +# name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_washer_remaining_time-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'device_class': 'power', - 'friendly_name': 'Machine à Laver Power', - 'power_consumption_end': '2025-04-25T08:43:46Z', - 'power_consumption_start': '2025-04-25T08:28:43Z', + 'device_class': 'duration', + 'friendly_name': 'Machine à Laver Washer remaining time', + 'icon': 'mdi:timer-sand', 'state_class': , - 'unit_of_measurement': , + 'unit_of_measurement': 'min', }), 'context': , - 'entity_id': 'sensor.machine_a_laver_power', + 'entity_id': 'sensor.machine_a_laver_washer_remaining_time', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': '0', + 'state': '100', }) # --- -# name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_power_energy-entry] +# name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_washing_progress-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + 'state_class': , }), 'config_entry_id': , 'config_subentry_id': , @@ -18565,7 +19784,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.machine_a_laver_power_energy', + 'entity_id': 'sensor.machine_a_laver_washing_progress', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -18573,38 +19792,35 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Power energy', + 'object_id_base': 'Washing progress', 'options': dict({ - 'sensor': dict({ - 'suggested_display_precision': 2, - }), }), - 'original_device_class': , - 'original_icon': None, - 'original_name': 'Power energy', + 'original_device_class': None, + 'original_icon': 'mdi:washing-machine', + 'original_name': 'Washing progress', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': 'power_energy', - 'unique_id': 'b854ca5f-dc54-140d-6349-758b4d973c41_main_powerConsumptionReport_powerConsumption_powerEnergy_meter', - 'unit_of_measurement': , + 'translation_key': 'washer_progress', + 'unique_id': 'b854ca5f-dc54-140d-6349-758b4d973c41_main_samsungce.washerOperatingState_progress_progress', + 'unit_of_measurement': '%', }) # --- -# name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_power_energy-state] +# name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_washing_progress-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'device_class': 'energy', - 'friendly_name': 'Machine à Laver Power energy', - 'state_class': , - 'unit_of_measurement': , + 'friendly_name': 'Machine à Laver Washing progress', + 'icon': 'mdi:washing-machine', + 'state_class': , + 'unit_of_measurement': '%', }), 'context': , - 'entity_id': 'sensor.machine_a_laver_power_energy', + 'entity_id': 'sensor.machine_a_laver_washing_progress', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': '0.0', + 'state': '40', }) # --- # name: test_all_entities[da_wm_wm_01011][sensor.machine_a_laver_water_consumption-entry] @@ -18866,6 +20082,120 @@ 'state': 'stop', }) # --- +# name: test_all_entities[da_wm_wm_100001][sensor.washer_1_washer_remaining_time-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.washer_1_washer_remaining_time', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Washer remaining time', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 2, + }), + }), + 'original_device_class': , + 'original_icon': 'mdi:timer-sand', + 'original_name': 'Washer remaining time', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'washer_remaining_time', + 'unique_id': 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_main_samsungce.washerOperatingState_remainingTime_remainingTime', + 'unit_of_measurement': 'min', + }) +# --- +# name: test_all_entities[da_wm_wm_100001][sensor.washer_1_washer_remaining_time-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'duration', + 'friendly_name': 'Washer 1 Washer remaining time', + 'icon': 'mdi:timer-sand', + 'state_class': , + 'unit_of_measurement': 'min', + }), + 'context': , + 'entity_id': 'sensor.washer_1_washer_remaining_time', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '57', + }) +# --- +# name: test_all_entities[da_wm_wm_100001][sensor.washer_1_washing_progress-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.washer_1_washing_progress', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Washing progress', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:washing-machine', + 'original_name': 'Washing progress', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'washer_progress', + 'unique_id': 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_main_samsungce.washerOperatingState_progress_progress', + 'unit_of_measurement': '%', + }) +# --- +# name: test_all_entities[da_wm_wm_100001][sensor.washer_1_washing_progress-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Washer 1 Washing progress', + 'icon': 'mdi:washing-machine', + 'state_class': , + 'unit_of_measurement': '%', + }), + 'context': , + 'entity_id': 'sensor.washer_1_washing_progress', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- # name: test_all_entities[da_wm_wm_100002][sensor.washer_2_completion_time-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ @@ -19067,82 +20397,14 @@ 'state': 'run', }) # --- -# name: test_all_entities[da_wm_wm_100002][sensor.washer_2_upper_washer_completion_time-entry] - EntityRegistryEntrySnapshot({ - 'aliases': list([ - None, - ]), - 'area_id': None, - 'capabilities': None, - 'config_entry_id': , - 'config_subentry_id': , - 'device_class': None, - 'device_id': , - 'disabled_by': None, - 'domain': 'sensor', - 'entity_category': None, - 'entity_id': 'sensor.washer_2_upper_washer_completion_time', - 'has_entity_name': True, - 'hidden_by': None, - 'icon': None, - 'id': , - 'labels': set({ - }), - 'name': None, - 'object_id_base': 'Upper washer completion time', - 'options': dict({ - }), - 'original_device_class': , - 'original_icon': None, - 'original_name': 'Upper washer completion time', - 'platform': 'smartthings', - 'previous_unique_id': None, - 'suggested_object_id': None, - 'supported_features': 0, - 'translation_key': 'washer_sub_completion_time', - 'unique_id': 'C097276D-C8D4-0000-0000-000000000000_sub_washerOperatingState_completionTime_completionTime', - 'unit_of_measurement': None, - }) -# --- -# name: test_all_entities[da_wm_wm_100002][sensor.washer_2_upper_washer_completion_time-state] - StateSnapshot({ - 'attributes': ReadOnlyDict({ - 'device_class': 'timestamp', - 'friendly_name': 'Washer 2 Upper washer completion time', - }), - 'context': , - 'entity_id': 'sensor.washer_2_upper_washer_completion_time', - 'last_changed': , - 'last_reported': , - 'last_updated': , - 'state': '2025-11-14T03:10:39+00:00', - }) -# --- -# name: test_all_entities[da_wm_wm_100002][sensor.washer_2_upper_washer_job_state-entry] +# name: test_all_entities[da_wm_wm_100002][sensor.washer_2_washer_remaining_time-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, ]), 'area_id': None, 'capabilities': dict({ - 'options': list([ - 'air_wash', - 'ai_rinse', - 'ai_spin', - 'ai_wash', - 'cooling', - 'delay_wash', - 'drying', - 'finish', - 'none', - 'pre_wash', - 'rinse', - 'spin', - 'wash', - 'weight_sensing', - 'wrinkle_prevent', - 'freeze_protection', - ]), + 'state_class': , }), 'config_entry_id': , 'config_subentry_id': , @@ -19151,7 +20413,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.washer_2_upper_washer_job_state', + 'entity_id': 'sensor.washer_2_washer_remaining_time', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -19159,65 +20421,49 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Upper washer job state', + 'object_id_base': 'Washer remaining time', 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 2, + }), }), - 'original_device_class': , - 'original_icon': None, - 'original_name': 'Upper washer job state', + 'original_device_class': , + 'original_icon': 'mdi:timer-sand', + 'original_name': 'Washer remaining time', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': 'washer_sub_job_state', - 'unique_id': 'C097276D-C8D4-0000-0000-000000000000_sub_washerOperatingState_washerJobState_washerJobState', - 'unit_of_measurement': None, + 'translation_key': 'washer_remaining_time', + 'unique_id': 'C097276D-C8D4-0000-0000-000000000000_main_samsungce.washerOperatingState_remainingTime_remainingTime', + 'unit_of_measurement': 'min', }) # --- -# name: test_all_entities[da_wm_wm_100002][sensor.washer_2_upper_washer_job_state-state] +# name: test_all_entities[da_wm_wm_100002][sensor.washer_2_washer_remaining_time-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'device_class': 'enum', - 'friendly_name': 'Washer 2 Upper washer job state', - 'options': list([ - 'air_wash', - 'ai_rinse', - 'ai_spin', - 'ai_wash', - 'cooling', - 'delay_wash', - 'drying', - 'finish', - 'none', - 'pre_wash', - 'rinse', - 'spin', - 'wash', - 'weight_sensing', - 'wrinkle_prevent', - 'freeze_protection', - ]), + 'device_class': 'duration', + 'friendly_name': 'Washer 2 Washer remaining time', + 'icon': 'mdi:timer-sand', + 'state_class': , + 'unit_of_measurement': 'min', }), 'context': , - 'entity_id': 'sensor.washer_2_upper_washer_job_state', + 'entity_id': 'sensor.washer_2_washer_remaining_time', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'none', + 'state': '5', }) # --- -# name: test_all_entities[da_wm_wm_100002][sensor.washer_2_upper_washer_machine_state-entry] +# name: test_all_entities[da_wm_wm_100002][sensor.washer_2_washing_progress-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ None, ]), 'area_id': None, 'capabilities': dict({ - 'options': list([ - 'pause', - 'run', - 'stop', - ]), + 'state_class': , }), 'config_entry_id': , 'config_subentry_id': , @@ -19226,7 +20472,7 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.washer_2_upper_washer_machine_state', + 'entity_id': 'sensor.washer_2_washing_progress', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -19234,38 +20480,35 @@ 'labels': set({ }), 'name': None, - 'object_id_base': 'Upper washer machine state', + 'object_id_base': 'Washing progress', 'options': dict({ }), - 'original_device_class': , - 'original_icon': None, - 'original_name': 'Upper washer machine state', + 'original_device_class': None, + 'original_icon': 'mdi:washing-machine', + 'original_name': 'Washing progress', 'platform': 'smartthings', 'previous_unique_id': None, 'suggested_object_id': None, 'supported_features': 0, - 'translation_key': 'washer_sub_machine_state', - 'unique_id': 'C097276D-C8D4-0000-0000-000000000000_sub_washerOperatingState_machineState_machineState', - 'unit_of_measurement': None, + 'translation_key': 'washer_progress', + 'unique_id': 'C097276D-C8D4-0000-0000-000000000000_main_samsungce.washerOperatingState_progress_progress', + 'unit_of_measurement': '%', }) # --- -# name: test_all_entities[da_wm_wm_100002][sensor.washer_2_upper_washer_machine_state-state] +# name: test_all_entities[da_wm_wm_100002][sensor.washer_2_washing_progress-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'device_class': 'enum', - 'friendly_name': 'Washer 2 Upper washer machine state', - 'options': list([ - 'pause', - 'run', - 'stop', - ]), + 'friendly_name': 'Washer 2 Washing progress', + 'icon': 'mdi:washing-machine', + 'state_class': , + 'unit_of_measurement': '%', }), 'context': , - 'entity_id': 'sensor.washer_2_upper_washer_machine_state', + 'entity_id': 'sensor.washer_2_washing_progress', 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'stop', + 'state': 'unknown', }) # --- # name: test_all_entities[ecobee_sensor][sensor.child_bedroom_temperature-entry] From 791deca34a8db689be29864bf57806ecf1407958 Mon Sep 17 00:00:00 2001 From: gielk Date: Thu, 21 May 2026 22:25:12 +0200 Subject: [PATCH 5/7] test(smartthings): add unit tests for cycle normalization and options fallback --- tests/components/smartthings/test_sensor.py | 110 +++++++++++++++++++- 1 file changed, 109 insertions(+), 1 deletion(-) diff --git a/tests/components/smartthings/test_sensor.py b/tests/components/smartthings/test_sensor.py index 6bd9b80705262..43061c4724331 100644 --- a/tests/components/smartthings/test_sensor.py +++ b/tests/components/smartthings/test_sensor.py @@ -1,10 +1,16 @@ """Test for the SmartThings sensors platform.""" -from unittest.mock import AsyncMock +from unittest.mock import AsyncMock, MagicMock from pysmartthings import Attribute, Capability from pysmartthings.models import HealthStatus import pytest + +from homeassistant.components.smartthings.sensor import ( + SmartThingsSensor, + SmartThingsSensorEntityDescription, + _normalize_cycle_value, +) from syrupy.assertion import SnapshotAssertion from homeassistant.components import automation, script @@ -393,3 +399,105 @@ async def test_availability_at_start( hass.states.get("sensor.theater_ac_office_granit_temperature").state == STATE_UNAVAILABLE ) + + +def test_normalize_cycle_value() -> None: + """Test cycle name normalization.""" + assert _normalize_cycle_value(None) is None + assert _normalize_cycle_value("") is None + assert _normalize_cycle_value("NORMAL_CYCLE") == "cycle" + assert _normalize_cycle_value("washer_delicate") == "delicate" + assert _normalize_cycle_value("delicate") == "delicate" + + +def test_sensor_options_and_fallback() -> None: + """Test options and fallback logic in SmartThingsSensor.""" + mock_client = MagicMock() + mock_device = MagicMock() + mock_device.device.device_id = "test-device-id" + mock_device.device.presentation_id = "test-presentation-id" + mock_device.online = True + + component = MAIN + capability = Capability.SAMSUNG_CE_WASHER_CYCLE + attribute = Attribute.WASHER_CYCLE + options_attribute = Attribute.SUPPORTED_CYCLES + + # Setup the mock attribute status values + mock_attribute_status = MagicMock() + mock_attribute_status.value = "unsupported_cycle" + mock_options_status = MagicMock() + mock_options_status.value = ["normal_cycle", "delicate_cycle"] + + mock_device.status = { + component: { + capability: { + attribute: mock_attribute_status, + options_attribute: mock_options_status, + } + } + } + + # 1. Test safety guard: native_value appended if not in dynamically retrieved options (line 1610) + desc = SmartThingsSensorEntityDescription( + key=attribute, + options_attribute=options_attribute, + ) + sensor = SmartThingsSensor( + client=mock_client, + device=mock_device, + entity_description=desc, + component=component, + capability=capability, + attribute=attribute, + ) + assert sensor.options == ["normal_cycle", "delicate_cycle", "unsupported_cycle"] + + # 2. Test fallback to static options if dynamic options value is None (lines 1614-1621) + mock_options_status.value = None + desc_with_static = SmartThingsSensorEntityDescription( + key=attribute, + options_attribute=options_attribute, + options=["static_1", "static_2"], + ) + sensor_static = SmartThingsSensor( + client=mock_client, + device=mock_device, + entity_description=desc_with_static, + component=component, + capability=capability, + attribute=attribute, + ) + assert sensor_static.options == ["static_1", "static_2", "unsupported_cycle"] + + # 3. Test returning empty list if dynamic options value is None and static options is None (line 1621) + desc_no_static = SmartThingsSensorEntityDescription( + key=attribute, + options_attribute=options_attribute, + options=None, + ) + sensor_no_static = SmartThingsSensor( + client=mock_client, + device=mock_device, + entity_description=desc_no_static, + component=component, + capability=capability, + attribute=attribute, + ) + assert sensor_no_static.options == [] + + # 4. Test safety guard for standard sensor (no dynamic options_attribute) appends native_value (line 1628) + desc_std = SmartThingsSensorEntityDescription( + key=attribute, + options_attribute=None, + options=["static_1", "static_2"], + ) + sensor_std = SmartThingsSensor( + client=mock_client, + device=mock_device, + entity_description=desc_std, + component=component, + capability=capability, + attribute=attribute, + ) + assert sensor_std.options == ["static_1", "static_2", "unsupported_cycle"] From 8210b02be1a122c0bb8aac8038fe32be50e77782 Mon Sep 17 00:00:00 2001 From: gielk Date: Fri, 22 May 2026 06:53:57 +0200 Subject: [PATCH 6/7] refactor(smartthings): fix option normalization, fallback, and washer sub entities --- .../components/smartthings/sensor.py | 85 +++--- .../components/smartthings/strings.json | 3 + .../smartthings/snapshots/test_sensor.ambr | 261 ++++++++++++++++++ tests/components/smartthings/test_sensor.py | 54 ++++ 4 files changed, 369 insertions(+), 34 deletions(-) diff --git a/homeassistant/components/smartthings/sensor.py b/homeassistant/components/smartthings/sensor.py index a5e38c5076613..7bd4e77fb0ecd 100644 --- a/homeassistant/components/smartthings/sensor.py +++ b/homeassistant/components/smartthings/sensor.py @@ -142,7 +142,16 @@ "UVPaused": "uv_paused", } -WASHER_OPTIONS = ["pause", "run", "stop"] +DISHWASHER_MACHINE_STATE_OPTIONS = ["pause", "run", "stop"] +WASHER_MACHINE_STATE_OPTIONS = [ + "pause", + "paused", + "ready", + "run", + "running", + "stop", +] + WASHER_CYCLES = [ "1c", @@ -426,7 +435,7 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription): SmartThingsSensorEntityDescription( key=Attribute.MACHINE_STATE, translation_key="dishwasher_machine_state", - options=WASHER_OPTIONS, + options=DISHWASHER_MACHINE_STATE_OPTIONS, device_class=SensorDeviceClass.ENUM, ) ], @@ -474,7 +483,7 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription): SmartThingsSensorEntityDescription( key=Attribute.MACHINE_STATE, translation_key="dryer_machine_state", - options=WASHER_OPTIONS, + options=WASHER_MACHINE_STATE_OPTIONS, device_class=SensorDeviceClass.ENUM, ) ], @@ -1214,8 +1223,9 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription): SmartThingsSensorEntityDescription( key=Attribute.MACHINE_STATE, translation_key="washer_machine_state", - options=WASHER_OPTIONS, + options=WASHER_MACHINE_STATE_OPTIONS, device_class=SensorDeviceClass.ENUM, + component_fn=lambda component: component == "sub", component_translation_key={ "sub": "washer_sub_machine_state", }, @@ -1245,6 +1255,7 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription): ], device_class=SensorDeviceClass.ENUM, value_fn=lambda value: JOB_STATE_MAP.get(value, value), + component_fn=lambda component: component == "sub", component_translation_key={ "sub": "washer_sub_job_state", }, @@ -1256,6 +1267,7 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription): translation_key="completion_time", device_class=SensorDeviceClass.TIMESTAMP, value_fn=lambda value: dt_util.parse_datetime(value) if value else None, + component_fn=lambda component: component == "sub", component_translation_key={ "sub": "washer_sub_completion_time", }, @@ -1594,38 +1606,43 @@ def options(self) -> list[str] | None: options_list = [] for option in options_val: if isinstance(option, dict): - opt_str = option.get("cycle") + opt_val = option.get("cycle") else: - opt_str = option - if opt_str is not None: - opt_str = str(opt_str) + opt_val = option + if opt_val is not None: if options_map := self.entity_description.options_map: - opt_str = options_map.get(opt_str, opt_str) - options_list.append(opt_str.lower()) - - # Guard against rejection: append current state if not present - if (current_value := self.native_value) is not None: - current_value_str = str(current_value) - if current_value_str not in options_list: - options_list.append(current_value_str) - return options_list - - # Fall back to static options in description if attribute is missing/None + opt_val = options_map.get(opt_val, opt_val) + else: + opt_val = self.entity_description.value_fn(opt_val) + if self.entity_description.presentation_fn: + opt_val = self.entity_description.presentation_fn( + self.device.device.presentation_id, opt_val + ) + if opt_val is not None: + options_list.append(str(opt_val).lower()) + else: + # Fall back to static options in description if attribute is missing/None + if (static_options := super().options) is not None: + options_list = [str(opt).lower() for opt in static_options] + else: + return [] + else: if (static_options := super().options) is not None: - options_list = list(static_options) - if (current_value := self.native_value) is not None: - current_value_str = str(current_value) - if current_value_str not in options_list: - options_list.append(current_value_str) - return options_list - return [] + options_list = [str(opt).lower() for opt in static_options] + else: + return None - if (static_options := super().options) is not None: - options_list = list(static_options) - if (current_value := self.native_value) is not None: - current_value_str = str(current_value) - if current_value_str not in options_list: - options_list.append(current_value_str) - return options_list + # Deduplicate while preserving order + seen: set[str] = set() + unique_options: list[str] = [] + for opt in options_list: + if opt not in seen: + seen.add(opt) + unique_options.append(opt) - return None + if (current_value := self.native_value) is not None: + current_value_str = str(current_value).lower() + if current_value_str not in seen: + unique_options.append(current_value_str) + + return unique_options diff --git a/homeassistant/components/smartthings/strings.json b/homeassistant/components/smartthings/strings.json index bee5a4fa0ddad..f28603953b16b 100644 --- a/homeassistant/components/smartthings/strings.json +++ b/homeassistant/components/smartthings/strings.json @@ -1048,7 +1048,10 @@ "name": "Upper washer machine state", "state": { "pause": "[%key:common::state::paused%]", + "paused": "[%key:common::state::paused%]", + "ready": "[%key:component::smartthings::entity::sensor::oven_machine_state::state::ready%]", "run": "[%key:component::smartthings::entity::sensor::dishwasher_machine_state::state::run%]", + "running": "[%key:component::smartthings::entity::sensor::dishwasher_machine_state::state::run%]", "stop": "[%key:common::state::stopped%]" } }, diff --git a/tests/components/smartthings/snapshots/test_sensor.ambr b/tests/components/smartthings/snapshots/test_sensor.ambr index e493cd1568f66..9135dd75aa62b 100644 --- a/tests/components/smartthings/snapshots/test_sensor.ambr +++ b/tests/components/smartthings/snapshots/test_sensor.ambr @@ -15484,7 +15484,10 @@ 'capabilities': dict({ 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -15525,7 +15528,10 @@ 'friendly_name': 'AirDresser Machine state', 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -16170,7 +16176,10 @@ 'capabilities': dict({ 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -16211,7 +16220,10 @@ 'friendly_name': 'Dryer Machine state', 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -16860,7 +16872,10 @@ 'capabilities': dict({ 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -16901,7 +16916,10 @@ 'friendly_name': 'Seca-Roupa Machine state', 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -17560,7 +17578,10 @@ 'capabilities': dict({ 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -17601,7 +17622,10 @@ 'friendly_name': 'Trockner Machine state', 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -18053,7 +18077,10 @@ 'capabilities': dict({ 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -18094,7 +18121,10 @@ 'friendly_name': 'Washer Machine state', 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -18741,7 +18771,10 @@ 'capabilities': dict({ 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -18782,7 +18815,10 @@ 'friendly_name': 'Washing Machine Machine state', 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -19433,7 +19469,10 @@ 'capabilities': dict({ 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -19474,7 +19513,10 @@ 'friendly_name': 'Machine à Laver Machine state', 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -20029,7 +20071,10 @@ 'capabilities': dict({ 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -20070,7 +20115,10 @@ 'friendly_name': 'Washer 1 Machine state', 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -20344,7 +20392,10 @@ 'capabilities': dict({ 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -20385,7 +20436,10 @@ 'friendly_name': 'Washer 2 Machine state', 'options': list([ 'pause', + 'paused', + 'ready', 'run', + 'running', 'stop', ]), }), @@ -20397,6 +20451,213 @@ 'state': 'run', }) # --- +# name: test_all_entities[da_wm_wm_100002][sensor.washer_2_upper_washer_completion_time-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.washer_2_upper_washer_completion_time', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Upper washer completion time', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Upper washer completion time', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'washer_sub_completion_time', + 'unique_id': 'C097276D-C8D4-0000-0000-000000000000_sub_washerOperatingState_completionTime_completionTime', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[da_wm_wm_100002][sensor.washer_2_upper_washer_completion_time-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'timestamp', + 'friendly_name': 'Washer 2 Upper washer completion time', + }), + 'context': , + 'entity_id': 'sensor.washer_2_upper_washer_completion_time', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2025-11-14T03:10:39+00:00', + }) +# --- +# name: test_all_entities[da_wm_wm_100002][sensor.washer_2_upper_washer_job_state-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'air_wash', + 'ai_rinse', + 'ai_spin', + 'ai_wash', + 'cooling', + 'delay_wash', + 'drying', + 'finish', + 'none', + 'pre_wash', + 'rinse', + 'spin', + 'wash', + 'weight_sensing', + 'wrinkle_prevent', + 'freeze_protection', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.washer_2_upper_washer_job_state', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Upper washer job state', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Upper washer job state', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'washer_sub_job_state', + 'unique_id': 'C097276D-C8D4-0000-0000-000000000000_sub_washerOperatingState_washerJobState_washerJobState', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[da_wm_wm_100002][sensor.washer_2_upper_washer_job_state-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Washer 2 Upper washer job state', + 'options': list([ + 'air_wash', + 'ai_rinse', + 'ai_spin', + 'ai_wash', + 'cooling', + 'delay_wash', + 'drying', + 'finish', + 'none', + 'pre_wash', + 'rinse', + 'spin', + 'wash', + 'weight_sensing', + 'wrinkle_prevent', + 'freeze_protection', + ]), + }), + 'context': , + 'entity_id': 'sensor.washer_2_upper_washer_job_state', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'none', + }) +# --- +# name: test_all_entities[da_wm_wm_100002][sensor.washer_2_upper_washer_machine_state-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'pause', + 'paused', + 'ready', + 'run', + 'running', + 'stop', + ]), + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.washer_2_upper_washer_machine_state', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Upper washer machine state', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Upper washer machine state', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'washer_sub_machine_state', + 'unique_id': 'C097276D-C8D4-0000-0000-000000000000_sub_washerOperatingState_machineState_machineState', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[da_wm_wm_100002][sensor.washer_2_upper_washer_machine_state-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Washer 2 Upper washer machine state', + 'options': list([ + 'pause', + 'paused', + 'ready', + 'run', + 'running', + 'stop', + ]), + }), + 'context': , + 'entity_id': 'sensor.washer_2_upper_washer_machine_state', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'stop', + }) +# --- # name: test_all_entities[da_wm_wm_100002][sensor.washer_2_washer_remaining_time-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ diff --git a/tests/components/smartthings/test_sensor.py b/tests/components/smartthings/test_sensor.py index 43061c4724331..d9e152b2c1ff0 100644 --- a/tests/components/smartthings/test_sensor.py +++ b/tests/components/smartthings/test_sensor.py @@ -501,3 +501,57 @@ def test_sensor_options_and_fallback() -> None: attribute=attribute, ) assert sensor_std.options == ["static_1", "static_2", "unsupported_cycle"] + + +def test_sensor_options_normalization_dict() -> None: + """Test option normalization (using value_fn), dictionary options and deduplication.""" + mock_client = MagicMock() + mock_device = MagicMock() + mock_device.device.device_id = "test-device-id" + mock_device.device.presentation_id = "test-presentation-id" + mock_device.online = True + + component = MAIN + capability = Capability.SAMSUNG_CE_WASHER_CYCLE + attribute = Attribute.WASHER_CYCLE + options_attribute = Attribute.SUPPORTED_CYCLES + + # Setup the mock attribute status values + mock_attribute_status = MagicMock() + mock_attribute_status.value = "NORMAL_CYCLE" + mock_options_status = MagicMock() + mock_options_status.value = [ + {"cycle": "NORMAL_CYCLE"}, + {"cycle": "DELICATE_CYCLE"}, + {"cycle": "Normal_Cycle"}, + ] + + mock_device.status = { + component: { + capability: { + attribute: mock_attribute_status, + options_attribute: mock_options_status, + } + } + } + + desc = SmartThingsSensorEntityDescription( + key=attribute, + options_attribute=options_attribute, + value_fn=_normalize_cycle_value, + ) + sensor = SmartThingsSensor( + client=mock_client, + device=mock_device, + entity_description=desc, + component=component, + capability=capability, + attribute=attribute, + ) + + assert sensor.options == ["cycle"] + + # Test with mixed-case strings that normalize to different values + mock_options_status.value = ["Wash_Normal", "Wash_Delicate", "wash_normal"] + assert sensor.options == ["normal", "delicate", "cycle"] + From e73a0bda56327943ad484225cb2629c1b055d97f Mon Sep 17 00:00:00 2001 From: gielk Date: Fri, 22 May 2026 07:03:02 +0200 Subject: [PATCH 7/7] style(smartthings): run ruff to fix import ordering and code formatting --- homeassistant/components/smartthings/sensor.py | 16 +++++++--------- tests/components/smartthings/test_sensor.py | 12 +++++------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/homeassistant/components/smartthings/sensor.py b/homeassistant/components/smartthings/sensor.py index 7bd4e77fb0ecd..d4d512ed4f93a 100644 --- a/homeassistant/components/smartthings/sensor.py +++ b/homeassistant/components/smartthings/sensor.py @@ -1620,17 +1620,15 @@ def options(self) -> list[str] | None: ) if opt_val is not None: options_list.append(str(opt_val).lower()) - else: - # Fall back to static options in description if attribute is missing/None - if (static_options := super().options) is not None: - options_list = [str(opt).lower() for opt in static_options] - else: - return [] - else: - if (static_options := super().options) is not None: + # Fall back to static options in description if attribute is missing/None + elif (static_options := super().options) is not None: options_list = [str(opt).lower() for opt in static_options] else: - return None + return [] + elif (static_options := super().options) is not None: + options_list = [str(opt).lower() for opt in static_options] + else: + return None # Deduplicate while preserving order seen: set[str] = set() diff --git a/tests/components/smartthings/test_sensor.py b/tests/components/smartthings/test_sensor.py index d9e152b2c1ff0..e451449da4ef7 100644 --- a/tests/components/smartthings/test_sensor.py +++ b/tests/components/smartthings/test_sensor.py @@ -5,12 +5,6 @@ from pysmartthings import Attribute, Capability from pysmartthings.models import HealthStatus import pytest - -from homeassistant.components.smartthings.sensor import ( - SmartThingsSensor, - SmartThingsSensorEntityDescription, - _normalize_cycle_value, -) from syrupy.assertion import SnapshotAssertion from homeassistant.components import automation, script @@ -18,6 +12,11 @@ from homeassistant.components.script import scripts_with_entity from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN from homeassistant.components.smartthings.const import DOMAIN, MAIN +from homeassistant.components.smartthings.sensor import ( + SmartThingsSensor, + SmartThingsSensorEntityDescription, + _normalize_cycle_value, +) from homeassistant.const import STATE_UNAVAILABLE, STATE_UNKNOWN, Platform from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er, issue_registry as ir @@ -554,4 +553,3 @@ def test_sensor_options_normalization_dict() -> None: # Test with mixed-case strings that normalize to different values mock_options_status.value = ["Wash_Normal", "Wash_Delicate", "wash_normal"] assert sensor.options == ["normal", "delicate", "cycle"] -