From d061f4ee05e2c1560a02029903b09f456e8d70fa Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Sun, 16 Mar 2025 20:06:50 +0100 Subject: [PATCH] Fix SmartThings ACs without supported AC modes (#140744) --- .../components/smartthings/climate.py | 15 ++-- tests/components/smartthings/conftest.py | 1 + .../fixtures/device_status/aux_ac.json | 69 ++++++++++++++++ .../smartthings/fixtures/devices/aux_ac.json | 81 +++++++++++++++++++ .../smartthings/snapshots/test_climate.ambr | 64 +++++++++++++++ .../smartthings/snapshots/test_init.ambr | 33 ++++++++ .../smartthings/snapshots/test_sensor.ambr | 52 ++++++++++++ 7 files changed, 309 insertions(+), 6 deletions(-) create mode 100644 tests/components/smartthings/fixtures/device_status/aux_ac.json create mode 100644 tests/components/smartthings/fixtures/devices/aux_ac.json diff --git a/homeassistant/components/smartthings/climate.py b/homeassistant/components/smartthings/climate.py index a95105efaa6..c6dee3e2be4 100644 --- a/homeassistant/components/smartthings/climate.py +++ b/homeassistant/components/smartthings/climate.py @@ -571,12 +571,15 @@ class SmartThingsAirConditioner(SmartThingsEntity, ClimateEntity): def _determine_hvac_modes(self) -> list[HVACMode]: """Determine the supported HVAC modes.""" modes = [HVACMode.OFF] - modes.extend( - state - for mode in self.get_attribute_value( + if ( + ac_modes := self.get_attribute_value( Capability.AIR_CONDITIONER_MODE, Attribute.SUPPORTED_AC_MODES ) - if (state := AC_MODE_TO_STATE.get(mode)) is not None - if state not in modes - ) + ) is not None: + modes.extend( + state + for mode in ac_modes + if (state := AC_MODE_TO_STATE.get(mode)) is not None + if state not in modes + ) return modes diff --git a/tests/components/smartthings/conftest.py b/tests/components/smartthings/conftest.py index 3e0047e255a..d26805eb04b 100644 --- a/tests/components/smartthings/conftest.py +++ b/tests/components/smartthings/conftest.py @@ -137,6 +137,7 @@ def mock_smartthings() -> Generator[AsyncMock]: "abl_light_b_001", "tplink_p110", "ikea_kadrilj", + "aux_ac", ] ) def device_fixture( diff --git a/tests/components/smartthings/fixtures/device_status/aux_ac.json b/tests/components/smartthings/fixtures/device_status/aux_ac.json new file mode 100644 index 00000000000..a3ebede7a10 --- /dev/null +++ b/tests/components/smartthings/fixtures/device_status/aux_ac.json @@ -0,0 +1,69 @@ +{ + "components": { + "main": { + "partyvoice23922.vtempset": { + "vtemp": { + "value": 20, + "unit": "C", + "timestamp": "2024-12-05T20:03:33.161Z" + } + }, + "airConditionerFanMode": { + "fanMode": { + "value": "auto", + "timestamp": "2024-12-05T20:03:32.930Z" + }, + "supportedAcFanModes": { + "value": null + }, + "availableAcFanModes": { + "value": null + } + }, + "temperatureMeasurement": { + "temperatureRange": { + "value": null + }, + "temperature": { + "value": 20.0, + "unit": "C", + "timestamp": "2024-12-05T20:03:33.066Z" + } + }, + "airConditionerMode": { + "availableAcModes": { + "value": null + }, + "supportedAcModes": { + "value": null + }, + "airConditionerMode": { + "value": "cool", + "timestamp": "2024-12-05T20:03:32.845Z" + } + }, + "fanSpeed": { + "fanSpeed": { + "value": 0, + "timestamp": "2024-12-05T20:03:33.334Z" + } + }, + "thermostatCoolingSetpoint": { + "coolingSetpointRange": { + "value": null + }, + "coolingSetpoint": { + "value": 20.0, + "unit": "C", + "timestamp": "2024-12-05T20:03:33.243Z" + } + }, + "switch": { + "switch": { + "value": "off", + "timestamp": "2024-12-05T20:03:32.662Z" + } + } + } + } +} diff --git a/tests/components/smartthings/fixtures/devices/aux_ac.json b/tests/components/smartthings/fixtures/devices/aux_ac.json new file mode 100644 index 00000000000..fcdb581748c --- /dev/null +++ b/tests/components/smartthings/fixtures/devices/aux_ac.json @@ -0,0 +1,81 @@ +{ + "items": [ + { + "deviceId": "bf53a150-f8a4-45d1-aac4-86252475d551", + "name": "vedgeaircon.v1", + "label": "AUX A/C on-off", + "manufacturerName": "SmartThingsCommunity", + "presentationId": "ab252042-5669-3c2c-8b1b-d606bbcc9e04", + "deviceManufacturerCode": "SmartThings Community", + "locationId": "5db1e3d8-ea26-44b4-8ed0-1ba9c841fd57", + "ownerId": "5404aa57-6a68-4fe2-83ff-168ef769d1c7", + "roomId": "564cdd9a-fa9f-4187-902f-95656ef22989", + "components": [ + { + "id": "main", + "label": "main", + "capabilities": [ + { + "id": "switch", + "version": 1 + }, + { + "id": "airConditionerMode", + "version": 1 + }, + { + "id": "thermostatCoolingSetpoint", + "version": 1 + }, + { + "id": "airConditionerFanMode", + "version": 1 + }, + { + "id": "fanSpeed", + "version": 1 + }, + { + "id": "temperatureMeasurement", + "version": 1 + }, + { + "id": "partyvoice23922.vtempset", + "version": 1 + } + ], + "categories": [ + { + "name": "AirConditioner", + "categoryType": "manufacturer" + } + ] + } + ], + "createTime": "2024-06-19T20:18:45.407Z", + "parentDeviceId": "e699599d-30f8-4cf0-8de7-6dbdba6a665f", + "profile": { + "id": "87f0ac35-e024-3c0a-8153-78ca27a6fe0c" + }, + "lan": { + "networkId": "vEdge_A/C_1718828324.999", + "driverId": "0fd9a9a4-8863-4a83-97a7-5a288ff0f5a6", + "executingLocally": true, + "hubId": "e699599d-30f8-4cf0-8de7-6dbdba6a665f", + "provisioningState": "TYPED" + }, + "type": "LAN", + "restrictionTier": 0, + "allowed": null, + "indoorMap": { + "coordinates": [130.0, 36.0, 378.0], + "rotation": [270.0, 0.0, 0.0], + "visible": true, + "data": null + }, + "executionContext": "LOCAL", + "relationships": [] + } + ], + "_links": {} +} diff --git a/tests/components/smartthings/snapshots/test_climate.ambr b/tests/components/smartthings/snapshots/test_climate.ambr index 20389f38a46..893093ee2aa 100644 --- a/tests/components/smartthings/snapshots/test_climate.ambr +++ b/tests/components/smartthings/snapshots/test_climate.ambr @@ -1,4 +1,68 @@ # serializer version: 1 +# name: test_all_entities[aux_ac][climate.aux_a_c_on_off-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'fan_modes': None, + 'hvac_modes': list([ + , + ]), + 'max_temp': 35, + 'min_temp': 7, + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'climate', + 'entity_category': None, + 'entity_id': 'climate.aux_a_c_on_off', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': None, + 'platform': 'smartthings', + 'previous_unique_id': None, + 'supported_features': , + 'translation_key': None, + 'unique_id': 'bf53a150-f8a4-45d1-aac4-86252475d551', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[aux_ac][climate.aux_a_c_on_off-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'current_temperature': 20.0, + 'fan_mode': 'auto', + 'fan_modes': None, + 'friendly_name': 'AUX A/C on-off', + 'hvac_modes': list([ + , + ]), + 'max_temp': 35, + 'min_temp': 7, + 'supported_features': , + 'temperature': 20.0, + }), + 'context': , + 'entity_id': 'climate.aux_a_c_on_off', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- # name: test_all_entities[bosch_radiator_thermostat_ii][climate.radiator_thermostat_ii_m_wohnzimmer-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ diff --git a/tests/components/smartthings/snapshots/test_init.ambr b/tests/components/smartthings/snapshots/test_init.ambr index 5a3ba833cf5..e62c34cd11c 100644 --- a/tests/components/smartthings/snapshots/test_init.ambr +++ b/tests/components/smartthings/snapshots/test_init.ambr @@ -68,6 +68,39 @@ 'via_device_id': None, }) # --- +# name: test_devices[aux_ac] + DeviceRegistryEntrySnapshot({ + 'area_id': None, + 'config_entries': , + 'config_entries_subentries': , + 'configuration_url': 'https://account.smartthings.com', + 'connections': set({ + }), + 'disabled_by': None, + 'entry_type': None, + 'hw_version': None, + 'id': , + 'identifiers': set({ + tuple( + 'smartthings', + 'bf53a150-f8a4-45d1-aac4-86252475d551', + ), + }), + 'is_new': False, + 'labels': set({ + }), + 'manufacturer': None, + 'model': None, + 'model_id': None, + 'name': 'AUX A/C on-off', + 'name_by_user': None, + 'primary_config_entry': , + 'serial_number': None, + 'suggested_area': None, + 'sw_version': None, + 'via_device_id': None, + }) +# --- # name: test_devices[base_electric_meter] DeviceRegistryEntrySnapshot({ 'area_id': 'theater', diff --git a/tests/components/smartthings/snapshots/test_sensor.ambr b/tests/components/smartthings/snapshots/test_sensor.ambr index d5ee2ffad22..954bcc5c281 100644 --- a/tests/components/smartthings/snapshots/test_sensor.ambr +++ b/tests/components/smartthings/snapshots/test_sensor.ambr @@ -154,6 +154,58 @@ 'state': 'unknown', }) # --- +# name: test_all_entities[aux_ac][sensor.aux_a_c_on_off_temperature-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + '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.aux_a_c_on_off_temperature', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Temperature', + 'platform': 'smartthings', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'bf53a150-f8a4-45d1-aac4-86252475d551.temperature', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[aux_ac][sensor.aux_a_c_on_off_temperature-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'temperature', + 'friendly_name': 'AUX A/C on-off Temperature', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.aux_a_c_on_off_temperature', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '20.0', + }) +# --- # name: test_all_entities[base_electric_meter][sensor.aeon_energy_monitor_energy-entry] EntityRegistryEntrySnapshot({ 'aliases': set({