mirror of
https://github.com/home-assistant/core.git
synced 2026-09-01 02:34:44 -05:00
Fix ValueError for non-numeric value in LG ThinQ (#166300)
Co-authored-by: YunseonPark-LGE <yunseon.park@lge.com>
This commit is contained in:
co-authored by
YunseonPark-LGE
parent
0cca80e57d
commit
4696e428cf
@@ -518,10 +518,6 @@ DEVICE_TYPE_SENSOR_MAP: dict[DeviceType, tuple[SensorEntityDescription, ...]] =
|
||||
),
|
||||
DeviceType.KIMCHI_REFRIGERATOR: (
|
||||
REFRIGERATION_SENSOR_DESC[ThinQProperty.FRESH_AIR_FILTER],
|
||||
SensorEntityDescription(
|
||||
key=ThinQProperty.TARGET_TEMPERATURE,
|
||||
translation_key=ThinQProperty.TARGET_TEMPERATURE,
|
||||
),
|
||||
),
|
||||
DeviceType.MICROWAVE_OVEN: (RUN_STATE_SENSOR_DESC[ThinQProperty.CURRENT_STATE],),
|
||||
DeviceType.OVEN: (
|
||||
@@ -592,6 +588,17 @@ DEVICE_TYPE_SENSOR_MAP: dict[DeviceType, tuple[SensorEntityDescription, ...]] =
|
||||
}
|
||||
|
||||
|
||||
ENUM_TEMPERATURE_SENSOR_MAP: dict[DeviceType, tuple[SensorEntityDescription, ...]] = {
|
||||
DeviceType.KIMCHI_REFRIGERATOR: (
|
||||
SensorEntityDescription(
|
||||
key=ThinQProperty.TARGET_TEMPERATURE,
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
translation_key=ThinQProperty.TARGET_TEMPERATURE,
|
||||
),
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class ThinQEnergySensorEntityDescription(SensorEntityDescription):
|
||||
"""Describes ThinQ energy sensor entity."""
|
||||
@@ -639,7 +646,9 @@ async def async_setup_entry(
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up an entry for sensor platform."""
|
||||
entities: list[ThinQSensorEntity | ThinQEnergySensorEntity] = []
|
||||
entities: list[
|
||||
ThinQSensorEntity | ThinQEnergySensorEntity | ThinQEnumTempSensorEntity
|
||||
] = []
|
||||
for coordinator in entry.runtime_data.coordinators.values():
|
||||
if (
|
||||
descriptions := DEVICE_TYPE_SENSOR_MAP.get(
|
||||
@@ -661,6 +670,21 @@ async def async_setup_entry(
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
if (
|
||||
descriptions := ENUM_TEMPERATURE_SENSOR_MAP.get(
|
||||
coordinator.api.device.device_type
|
||||
)
|
||||
) is not None:
|
||||
for description in descriptions:
|
||||
entities.extend(
|
||||
ThinQEnumTempSensorEntity(coordinator, description, property_id)
|
||||
for property_id in coordinator.api.get_active_idx(
|
||||
description.key,
|
||||
ActiveMode.READ_ONLY,
|
||||
)
|
||||
)
|
||||
|
||||
for energy_description in ENERGY_USAGE_SENSORS:
|
||||
entities.extend(
|
||||
ThinQEnergySensorEntity(
|
||||
@@ -860,3 +884,38 @@ class ThinQEnergySensorEntity(ThinQEntity, SensorEntity):
|
||||
self.async_update,
|
||||
next_update,
|
||||
)
|
||||
|
||||
|
||||
class ThinQEnumTempSensorEntity(ThinQEntity, SensorEntity):
|
||||
"""Represent a thinq sensor platform."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: DeviceDataUpdateCoordinator,
|
||||
entity_description: SensorEntityDescription,
|
||||
property_id: str,
|
||||
) -> None:
|
||||
"""Initialize a sensor entity."""
|
||||
super().__init__(coordinator, entity_description, property_id)
|
||||
|
||||
if self.data.options:
|
||||
# some kimchi refrigerator's target temperature have data in the form of string with enum options.
|
||||
# Set options to display the correct value in the UI.
|
||||
self._attr_options = self.data.options
|
||||
self._attr_device_class = SensorDeviceClass.ENUM
|
||||
self._attr_native_unit_of_measurement = None
|
||||
|
||||
def _update_status(self) -> None:
|
||||
"""Update status itself."""
|
||||
super()._update_status()
|
||||
self._attr_native_value = self.data.value
|
||||
|
||||
_LOGGER.debug(
|
||||
"[%s:%s] update status: %s -> %s, options:%s, unit:%s",
|
||||
self.coordinator.device_name,
|
||||
self.property_id,
|
||||
self.data.value,
|
||||
self.native_value,
|
||||
self.options,
|
||||
self.native_unit_of_measurement,
|
||||
)
|
||||
|
||||
@@ -117,6 +117,7 @@ def mock_thinq_mqtt_client() -> Generator[None]:
|
||||
"air_conditioner",
|
||||
"washer",
|
||||
"dehumidifier",
|
||||
"kimchi_refrigerator",
|
||||
]
|
||||
)
|
||||
def device_fixture(request: pytest.FixtureRequest) -> Generator[str]:
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"deviceId": "MW2-FD94EF23-EF86-4D65-92AB-5399A90C228F",
|
||||
"deviceInfo": {
|
||||
"deviceType": "DEVICE_KIMCHI_REFRIGERATOR",
|
||||
"modelName": "2REB1KRS11__H",
|
||||
"alias": "Test kimchi refrigerator",
|
||||
"reportable": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"resultCode": "0000",
|
||||
"result": {
|
||||
"property": ["energyUsage"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"notification": {
|
||||
"push": ["DOOR_IS_OPEN"]
|
||||
},
|
||||
"property": {
|
||||
"temperature": [
|
||||
{
|
||||
"locationName": "TOP",
|
||||
"targetTemperature": {
|
||||
"mode": ["r"],
|
||||
"type": "enum",
|
||||
"value": {
|
||||
"r": ["TEMPERATURE_NUMBER"]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"locationName": "MIDDLE",
|
||||
"targetTemperature": {
|
||||
"mode": ["r"],
|
||||
"type": "enum",
|
||||
"value": {
|
||||
"r": ["KIMCHI", "MEAT_FISH", "VEGETABLE_FRUIT"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"temperature": [
|
||||
{
|
||||
"locationName": "TOP",
|
||||
"targetTemperature": 6
|
||||
},
|
||||
{
|
||||
"locationName": "MIDDLE",
|
||||
"targetTemperature": "KIMCHI"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -605,3 +605,290 @@
|
||||
'state': '2024-10-10T13:14:00+00:00',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities[kimchi_refrigerator][sensor.test_kimchi_refrigerator_energy_last_month-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.TOTAL: 'total'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.test_kimchi_refrigerator_energy_last_month',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Energy last month',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 0,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Energy last month',
|
||||
'platform': 'lg_thinq',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'energy_usage_last_month',
|
||||
'unique_id': 'MW2-FD94EF23-EF86-4D65-92AB-5399A90C228F_energyUsage_last_month',
|
||||
'unit_of_measurement': <UnitOfEnergy.WATT_HOUR: 'Wh'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities[kimchi_refrigerator][sensor.test_kimchi_refrigerator_energy_last_month-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'energy',
|
||||
'friendly_name': 'Test kimchi refrigerator Energy last month',
|
||||
'state_class': <SensorStateClass.TOTAL: 'total'>,
|
||||
'unit_of_measurement': <UnitOfEnergy.WATT_HOUR: 'Wh'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.test_kimchi_refrigerator_energy_last_month',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities[kimchi_refrigerator][sensor.test_kimchi_refrigerator_energy_this_month-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.test_kimchi_refrigerator_energy_this_month',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Energy this month',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 0,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Energy this month',
|
||||
'platform': 'lg_thinq',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'energy_usage_this_month',
|
||||
'unique_id': 'MW2-FD94EF23-EF86-4D65-92AB-5399A90C228F_energyUsage_this_month',
|
||||
'unit_of_measurement': <UnitOfEnergy.WATT_HOUR: 'Wh'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities[kimchi_refrigerator][sensor.test_kimchi_refrigerator_energy_this_month-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'energy',
|
||||
'friendly_name': 'Test kimchi refrigerator Energy this month',
|
||||
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||
'unit_of_measurement': <UnitOfEnergy.WATT_HOUR: 'Wh'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.test_kimchi_refrigerator_energy_this_month',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities[kimchi_refrigerator][sensor.test_kimchi_refrigerator_energy_yesterday-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.TOTAL: 'total'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.test_kimchi_refrigerator_energy_yesterday',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Energy yesterday',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 0,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Energy yesterday',
|
||||
'platform': 'lg_thinq',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'energy_usage_yesterday',
|
||||
'unique_id': 'MW2-FD94EF23-EF86-4D65-92AB-5399A90C228F_energyUsage_yesterday',
|
||||
'unit_of_measurement': <UnitOfEnergy.WATT_HOUR: 'Wh'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities[kimchi_refrigerator][sensor.test_kimchi_refrigerator_energy_yesterday-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'energy',
|
||||
'friendly_name': 'Test kimchi refrigerator Energy yesterday',
|
||||
'state_class': <SensorStateClass.TOTAL: 'total'>,
|
||||
'unit_of_measurement': <UnitOfEnergy.WATT_HOUR: 'Wh'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.test_kimchi_refrigerator_energy_yesterday',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities[kimchi_refrigerator][sensor.test_kimchi_refrigerator_middle_temperature-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'options': list([
|
||||
'kimchi',
|
||||
'meat_fish',
|
||||
'vegetable_fruit',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.test_kimchi_refrigerator_middle_temperature',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'middle temperature',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'middle temperature',
|
||||
'platform': 'lg_thinq',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'target_temperature_for_location',
|
||||
'unique_id': 'MW2-FD94EF23-EF86-4D65-92AB-5399A90C228F_middle_target_temperature',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities[kimchi_refrigerator][sensor.test_kimchi_refrigerator_middle_temperature-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'enum',
|
||||
'friendly_name': 'Test kimchi refrigerator middle temperature',
|
||||
'options': list([
|
||||
'kimchi',
|
||||
'meat_fish',
|
||||
'vegetable_fruit',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.test_kimchi_refrigerator_middle_temperature',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'kimchi',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities[kimchi_refrigerator][sensor.test_kimchi_refrigerator_top_temperature-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.test_kimchi_refrigerator_top_temperature',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'top temperature',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'top temperature',
|
||||
'platform': 'lg_thinq',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'target_temperature_for_location',
|
||||
'unique_id': 'MW2-FD94EF23-EF86-4D65-92AB-5399A90C228F_top_target_temperature',
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor_entities[kimchi_refrigerator][sensor.test_kimchi_refrigerator_top_temperature-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Test kimchi refrigerator top temperature',
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.test_kimchi_refrigerator_top_temperature',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '6',
|
||||
})
|
||||
# ---
|
||||
|
||||
@@ -23,7 +23,7 @@ from tests.common import (
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device_fixture", ["air_conditioner"])
|
||||
@pytest.mark.parametrize("device_fixture", ["air_conditioner", "kimchi_refrigerator"])
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
@pytest.mark.freeze_time(datetime(2024, 10, 10, tzinfo=UTC))
|
||||
async def test_sensor_entities(
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import Platform
|
||||
@@ -13,6 +14,10 @@ from . import setup_integration
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
@pytest.mark.parametrize(
|
||||
"device_fixture", ["air_conditioner", "dehumidifier", "washer"]
|
||||
)
|
||||
async def test_switch_entities(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
|
||||
Reference in New Issue
Block a user