Fix missing operation select for LG ThinQ WashTower dryer (#177020)

Co-authored-by: Joostlek <joostlek@outlook.com>
This commit is contained in:
wbradmoore
2026-07-26 22:22:59 +02:00
committed by GitHub
co-authored by Joostlek
parent 9aed13698c
commit a4a649d75a
7 changed files with 590 additions and 1 deletions
+1 -1
View File
@@ -134,7 +134,7 @@ DEVICE_TYPE_SELECT_MAP: dict[DeviceType, tuple[SelectEntityDescription, ...]] =
),
DeviceType.WASHER: (OPERATION_SELECT_DESC[ThinQProperty.WASHER_OPERATION_MODE],),
DeviceType.WASHTOWER_DRYER: (
OPERATION_SELECT_DESC[ThinQProperty.WASHER_OPERATION_MODE],
OPERATION_SELECT_DESC[ThinQProperty.DRYER_OPERATION_MODE],
),
DeviceType.WASHTOWER: (
OPERATION_SELECT_DESC[ThinQProperty.DRYER_OPERATION_MODE],
@@ -0,0 +1,9 @@
{
"deviceId": "MW2-1E7C3325-9C2B-4E1F-8D64-0A5B7C11F203",
"deviceInfo": {
"deviceType": "DEVICE_WASHTOWER_DRYER",
"modelName": "W3S1CVK2EVS",
"alias": "Test washtower dryer",
"reportable": true
}
}
@@ -0,0 +1,6 @@
{
"resultCode": "0000",
"result": {
"property": []
}
}
@@ -0,0 +1,154 @@
{
"notification": {
"push": ["DRYING_IS_COMPLETE", "ERROR_DURING_DRYING"]
},
"property": {
"operation": {
"dryerOperationMode": {
"mode": ["w"],
"type": "enum",
"value": {
"w": ["START", "STOP", "POWER_OFF", "POWER_ON"]
}
}
},
"remoteControlEnable": {
"remoteControlEnabled": {
"mode": ["r"],
"type": "boolean",
"value": {
"r": [false, true]
}
}
},
"runState": {
"currentState": {
"mode": ["r"],
"type": "enum",
"value": {
"r": [
"POWER_OFF",
"INITIAL",
"RUNNING",
"PAUSE",
"COOLING",
"END",
"ERROR",
"RESERVED",
"SLEEP"
]
}
}
},
"timer": {
"relativeHourToStart": {
"mode": ["r", "w"],
"type": "range",
"value": {
"r": {
"except": [],
"max": 19,
"min": 1,
"step": 1
},
"w": {
"except": [],
"max": 19,
"min": 1,
"step": 1
}
}
},
"relativeMinuteToStart": {
"mode": ["r"],
"type": "range",
"value": {
"r": {
"except": [],
"max": 30,
"min": 0,
"step": 1
}
}
},
"relativeHourToStop": {
"mode": ["r", "w"],
"type": "range",
"value": {
"r": {
"except": [],
"max": 19,
"min": 1,
"step": 1
},
"w": {
"except": [],
"max": 19,
"min": 1,
"step": 1
}
}
},
"relativeMinuteToStop": {
"mode": ["r"],
"type": "range",
"value": {
"r": {
"except": [],
"max": 59,
"min": 0,
"step": 1
}
}
},
"remainHour": {
"mode": ["r"],
"type": "range",
"value": {
"r": {
"except": [],
"max": 30,
"min": 0,
"step": 1
}
}
},
"remainMinute": {
"mode": ["r"],
"type": "range",
"value": {
"r": {
"except": [],
"max": 59,
"min": 0,
"step": 1
}
}
},
"totalHour": {
"mode": ["r"],
"type": "range",
"value": {
"r": {
"except": [],
"max": 30,
"min": 0,
"step": 1
}
}
},
"totalMinute": {
"mode": ["r"],
"type": "range",
"value": {
"r": {
"except": [],
"max": 59,
"min": 0,
"step": 1
}
}
}
}
}
}
@@ -0,0 +1,18 @@
{
"remoteControlEnable": {
"remoteControlEnabled": true
},
"runState": {
"currentState": "POWER_OFF"
},
"timer": {
"relativeHourToStart": 0,
"relativeMinuteToStart": 0,
"relativeHourToStop": 0,
"relativeMinuteToStop": 0,
"remainHour": 0,
"remainMinute": 41,
"totalHour": 0,
"totalMinute": 41
}
}
@@ -0,0 +1,369 @@
# serializer version: 1
# name: test_select_entities[air_conditioner][select.test_air_conditioner_air_purify-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': dict({
<SelectEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'start',
'stop',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'select',
'entity_category': None,
'entity_id': 'select.test_air_conditioner_air_purify',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Air purify',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Air purify',
'platform': 'lg_thinq',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'air_clean_operation_mode',
'unique_id': 'MW2-2E247F93-B570-46A6-B827-920E9E10F966_air_clean_operation_mode',
'unit_of_measurement': None,
})
# ---
# name: test_select_entities[air_conditioner][select.test_air_conditioner_air_purify-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test air conditioner Air purify',
<SelectEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'start',
'stop',
]),
}),
'context': <ANY>,
'entity_id': 'select.test_air_conditioner_air_purify',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---
# name: test_select_entities[air_conditioner][select.test_air_conditioner_air_quality_sensor-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': dict({
<SelectEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'on_working',
'always',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'select',
'entity_category': None,
'entity_id': 'select.test_air_conditioner_air_quality_sensor',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Air quality sensor',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Air quality sensor',
'platform': 'lg_thinq',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <Property.MONITORING_ENABLED: 'monitoring_enabled'>,
'unique_id': 'MW2-2E247F93-B570-46A6-B827-920E9E10F966_monitoring_enabled',
'unit_of_measurement': None,
})
# ---
# name: test_select_entities[air_conditioner][select.test_air_conditioner_air_quality_sensor-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test air conditioner Air quality sensor',
<SelectEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'on_working',
'always',
]),
}),
'context': <ANY>,
'entity_id': 'select.test_air_conditioner_air_quality_sensor',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on_working',
})
# ---
# name: test_select_entities[dehumidifier][select.test_dehumidifier_operating_mode-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': dict({
<SelectEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'smart_humidity',
'intensive_dry',
'rapid_humidity',
'quiet_humidity',
'clothes_dry',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'select',
'entity_category': None,
'entity_id': 'select.test_dehumidifier_operating_mode',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Operating mode',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Operating mode',
'platform': 'lg_thinq',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'current_job_mode_dehumidifier',
'unique_id': 'TQS-25A89504-EF8E-4C4E-99F3-3956ED3BD397_current_job_mode',
'unit_of_measurement': None,
})
# ---
# name: test_select_entities[dehumidifier][select.test_dehumidifier_operating_mode-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test dehumidifier Operating mode',
<SelectEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'smart_humidity',
'intensive_dry',
'rapid_humidity',
'quiet_humidity',
'clothes_dry',
]),
}),
'context': <ANY>,
'entity_id': 'select.test_dehumidifier_operating_mode',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'smart_humidity',
})
# ---
# name: test_select_entities[dehumidifier][select.test_dehumidifier_speed-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': dict({
<SelectEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'low',
'high',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'select',
'entity_category': None,
'entity_id': 'select.test_dehumidifier_speed',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Speed',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Speed',
'platform': 'lg_thinq',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <Property.WIND_STRENGTH: 'wind_strength'>,
'unique_id': 'TQS-25A89504-EF8E-4C4E-99F3-3956ED3BD397_wind_strength',
'unit_of_measurement': None,
})
# ---
# name: test_select_entities[dehumidifier][select.test_dehumidifier_speed-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test dehumidifier Speed',
<SelectEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'low',
'high',
]),
}),
'context': <ANY>,
'entity_id': 'select.test_dehumidifier_speed',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'high',
})
# ---
# name: test_select_entities[washer][select.test_washer_operation-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': dict({
<SelectEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'start',
'stop',
'power_off',
'power_on',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'select',
'entity_category': None,
'entity_id': 'select.test_washer_operation',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Operation',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Operation',
'platform': 'lg_thinq',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'operation_mode',
'unique_id': 'MW2-0B530EFD-1ADF-4F54-A2C3-46C37F94C689_main_washer_operation_mode',
'unit_of_measurement': None,
})
# ---
# name: test_select_entities[washer][select.test_washer_operation-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test washer Operation',
<SelectEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'start',
'stop',
'power_off',
'power_on',
]),
}),
'context': <ANY>,
'entity_id': 'select.test_washer_operation',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---
# name: test_select_entities[washtower_dryer][select.test_washtower_dryer_operation-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': dict({
<SelectEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'start',
'stop',
'power_off',
'power_on',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'select',
'entity_category': None,
'entity_id': 'select.test_washtower_dryer_operation',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Operation',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Operation',
'platform': 'lg_thinq',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'operation_mode',
'unique_id': 'MW2-1E7C3325-9C2B-4E1F-8D64-0A5B7C11F203_dryer_operation_mode',
'unit_of_measurement': None,
})
# ---
# name: test_select_entities[washtower_dryer][select.test_washtower_dryer_operation-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test washtower dryer Operation',
<SelectEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'start',
'stop',
'power_off',
'power_on',
]),
}),
'context': <ANY>,
'entity_id': 'select.test_washtower_dryer_operation',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---
+33
View File
@@ -0,0 +1,33 @@
"""Tests for the LG ThinQ select platform."""
from unittest.mock import AsyncMock, patch
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import setup_integration
from tests.common import MockConfigEntry, snapshot_platform
@pytest.mark.parametrize(
"device_fixture",
["air_conditioner", "dehumidifier", "washer", "washtower_dryer"],
)
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_select_entities(
hass: HomeAssistant,
snapshot: SnapshotAssertion,
devices: AsyncMock,
mock_config_entry: MockConfigEntry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test all entities."""
with patch("homeassistant.components.lg_thinq.PLATFORMS", [Platform.SELECT]):
await setup_integration(hass, mock_config_entry)
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)