diff --git a/homeassistant/components/tuya/humidifier.py b/homeassistant/components/tuya/humidifier.py index 5def5c5e16c..cb08ccaf476 100644 --- a/homeassistant/components/tuya/humidifier.py +++ b/homeassistant/components/tuya/humidifier.py @@ -35,6 +35,20 @@ class TuyaHumidifierEntityDescription(HumidifierEntityDescription): humidity: DPCode | None = None +def _has_a_valid_dpcode( + device: CustomerDevice, description: TuyaHumidifierEntityDescription +) -> bool: + """Check if the device has at least one valid DP code.""" + properties_to_check: list[DPCode | tuple[DPCode, ...] | None] = [ + # Main control switch + description.dpcode or DPCode(description.key), + # Other humidity properties + description.current_humidity, + description.humidity, + ] + return any(get_dpcode(device, code) for code in properties_to_check) + + HUMIDIFIERS: dict[str, TuyaHumidifierEntityDescription] = { # Dehumidifier # https://developer.tuya.com/en/docs/iot/categorycs?id=Kaiuz1vcz4dha @@ -71,7 +85,9 @@ async def async_setup_entry( entities: list[TuyaHumidifierEntity] = [] for device_id in device_ids: device = hass_data.manager.device_map[device_id] - if description := HUMIDIFIERS.get(device.category): + if ( + description := HUMIDIFIERS.get(device.category) + ) and _has_a_valid_dpcode(device, description): entities.append( TuyaHumidifierEntity(device, hass_data.manager, description) ) diff --git a/tests/components/tuya/snapshots/test_humidifier.ambr b/tests/components/tuya/snapshots/test_humidifier.ambr index ab172241bfa..46535810d7d 100644 --- a/tests/components/tuya/snapshots/test_humidifier.ambr +++ b/tests/components/tuya/snapshots/test_humidifier.ambr @@ -55,61 +55,6 @@ }) # --- # name: test_platform_setup_and_discovery[humidifier.dehumidifier-entry] - EntityRegistryEntrySnapshot({ - 'aliases': set({ - }), - 'area_id': None, - 'capabilities': dict({ - 'max_humidity': 100, - 'min_humidity': 0, - }), - 'config_entry_id': , - 'config_subentry_id': , - 'device_class': None, - 'device_id': , - 'disabled_by': None, - 'domain': 'humidifier', - 'entity_category': None, - 'entity_id': 'humidifier.dehumidifier', - 'has_entity_name': True, - 'hidden_by': None, - 'icon': None, - 'id': , - 'labels': set({ - }), - 'name': None, - 'options': dict({ - }), - 'original_device_class': , - 'original_icon': None, - 'original_name': None, - 'platform': 'tuya', - 'previous_unique_id': None, - 'suggested_object_id': None, - 'supported_features': 0, - 'translation_key': None, - 'unique_id': 'tuya.ilms5pwjzzsxuxmvscswitch', - 'unit_of_measurement': None, - }) -# --- -# name: test_platform_setup_and_discovery[humidifier.dehumidifier-state] - StateSnapshot({ - 'attributes': ReadOnlyDict({ - 'device_class': 'dehumidifier', - 'friendly_name': 'Dehumidifier ', - 'max_humidity': 100, - 'min_humidity': 0, - 'supported_features': , - }), - 'context': , - 'entity_id': 'humidifier.dehumidifier', - 'last_changed': , - 'last_reported': , - 'last_updated': , - 'state': 'off', - }) -# --- -# name: test_platform_setup_and_discovery[humidifier.dehumidifier_2-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ }), @@ -125,7 +70,7 @@ 'disabled_by': None, 'domain': 'humidifier', 'entity_category': None, - 'entity_id': 'humidifier.dehumidifier_2', + 'entity_id': 'humidifier.dehumidifier', 'has_entity_name': True, 'hidden_by': None, 'icon': None, @@ -147,7 +92,7 @@ 'unit_of_measurement': None, }) # --- -# name: test_platform_setup_and_discovery[humidifier.dehumidifier_2-state] +# name: test_platform_setup_and_discovery[humidifier.dehumidifier-state] StateSnapshot({ 'attributes': ReadOnlyDict({ 'current_humidity': 47, @@ -159,65 +104,10 @@ 'supported_features': , }), 'context': , - 'entity_id': 'humidifier.dehumidifier_2', + 'entity_id': 'humidifier.dehumidifier', 'last_changed': , 'last_reported': , 'last_updated': , 'state': 'on', }) # --- -# name: test_platform_setup_and_discovery[humidifier.dryfix-entry] - EntityRegistryEntrySnapshot({ - 'aliases': set({ - }), - 'area_id': None, - 'capabilities': dict({ - 'max_humidity': 100, - 'min_humidity': 0, - }), - 'config_entry_id': , - 'config_subentry_id': , - 'device_class': None, - 'device_id': , - 'disabled_by': None, - 'domain': 'humidifier', - 'entity_category': None, - 'entity_id': 'humidifier.dryfix', - 'has_entity_name': True, - 'hidden_by': None, - 'icon': None, - 'id': , - 'labels': set({ - }), - 'name': None, - 'options': dict({ - }), - 'original_device_class': , - 'original_icon': None, - 'original_name': None, - 'platform': 'tuya', - 'previous_unique_id': None, - 'suggested_object_id': None, - 'supported_features': 0, - 'translation_key': None, - 'unique_id': 'tuya.hz4pau766eavmxhqscswitch', - 'unit_of_measurement': None, - }) -# --- -# name: test_platform_setup_and_discovery[humidifier.dryfix-state] - StateSnapshot({ - 'attributes': ReadOnlyDict({ - 'device_class': 'dehumidifier', - 'friendly_name': 'DryFix', - 'max_humidity': 100, - 'min_humidity': 0, - 'supported_features': , - }), - 'context': , - 'entity_id': 'humidifier.dryfix', - 'last_changed': , - 'last_reported': , - 'last_updated': , - 'state': 'unavailable', - }) -# --- diff --git a/tests/components/tuya/test_humidifier.py b/tests/components/tuya/test_humidifier.py index debfb765d8b..33f715176bd 100644 --- a/tests/components/tuya/test_humidifier.py +++ b/tests/components/tuya/test_humidifier.py @@ -126,7 +126,7 @@ async def test_set_humidity( @pytest.mark.parametrize( "mock_device_code", - ["cs_vmxuxszzjwp5smli"], + ["cs_zibqa9dutqyaxym2"], ) async def test_turn_on_unsupported( hass: HomeAssistant, @@ -135,6 +135,11 @@ async def test_turn_on_unsupported( mock_device: CustomerDevice, ) -> None: """Test turn on service (not supported by this device).""" + # Remove switch control - but keep other functionality + mock_device.status.pop("switch") + mock_device.function.pop("switch") + mock_device.status_range.pop("switch") + entity_id = "humidifier.dehumidifier" await initialize_entry(hass, mock_manager, mock_config_entry, mock_device) @@ -150,13 +155,13 @@ async def test_turn_on_unsupported( assert err.value.translation_key == "action_dpcode_not_found" assert err.value.translation_placeholders == { "expected": "['switch', 'switch_spray']", - "available": ("[]"), + "available": ("['child_lock', 'countdown_set', 'dehumidify_set_value']"), } @pytest.mark.parametrize( "mock_device_code", - ["cs_vmxuxszzjwp5smli"], + ["cs_zibqa9dutqyaxym2"], ) async def test_turn_off_unsupported( hass: HomeAssistant, @@ -165,6 +170,11 @@ async def test_turn_off_unsupported( mock_device: CustomerDevice, ) -> None: """Test turn off service (not supported by this device).""" + # Remove switch control - but keep other functionality + mock_device.status.pop("switch") + mock_device.function.pop("switch") + mock_device.status_range.pop("switch") + entity_id = "humidifier.dehumidifier" await initialize_entry(hass, mock_manager, mock_config_entry, mock_device) @@ -180,13 +190,13 @@ async def test_turn_off_unsupported( assert err.value.translation_key == "action_dpcode_not_found" assert err.value.translation_placeholders == { "expected": "['switch', 'switch_spray']", - "available": ("[]"), + "available": ("['child_lock', 'countdown_set', 'dehumidify_set_value']"), } @pytest.mark.parametrize( "mock_device_code", - ["cs_vmxuxszzjwp5smli"], + ["cs_zibqa9dutqyaxym2"], ) async def test_set_humidity_unsupported( hass: HomeAssistant, @@ -195,6 +205,11 @@ async def test_set_humidity_unsupported( mock_device: CustomerDevice, ) -> None: """Test set humidity service (not supported by this device).""" + # Remove set humidity control - but keep other functionality + mock_device.status.pop("dehumidify_set_value") + mock_device.function.pop("dehumidify_set_value") + mock_device.status_range.pop("dehumidify_set_value") + entity_id = "humidifier.dehumidifier" await initialize_entry(hass, mock_manager, mock_config_entry, mock_device) @@ -213,5 +228,5 @@ async def test_set_humidity_unsupported( assert err.value.translation_key == "action_dpcode_not_found" assert err.value.translation_placeholders == { "expected": "['dehumidify_set_value']", - "available": ("[]"), + "available": ("['child_lock', 'countdown_set', 'switch']"), }