diff --git a/custom_components/xiaomi_miot/__init__.py b/custom_components/xiaomi_miot/__init__.py index 68d70f473d..e08fce5644 100644 --- a/custom_components/xiaomi_miot/__init__.py +++ b/custom_components/xiaomi_miot/__init__.py @@ -1255,7 +1255,6 @@ async def async_update(self): async def async_update_for_main_entity(self): if self._miot_service: for d in [ - 'sensor', 'binary_sensor', 'switch', 'number', 'select', 'fan', 'cover', 'button', 'scanner', 'number_select', ]: pls = self.custom_config_list(f'{d}_properties') or [] diff --git a/custom_components/xiaomi_miot/binary_sensor.py b/custom_components/xiaomi_miot/binary_sensor.py index 60e7f359c2..72c9a5b018 100644 --- a/custom_components/xiaomi_miot/binary_sensor.py +++ b/custom_components/xiaomi_miot/binary_sensor.py @@ -14,6 +14,7 @@ BinarySensorEntity as BaseEntity, BinarySensorDeviceClass, ) +from homeassistant.helpers.restore_state import RestoreEntity from . import ( DOMAIN, @@ -85,7 +86,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= bind_services_to_entries(hass, SERVICE_TO_METHOD) -class BinarySensorEntity(XEntity, BaseEntity): +class BinarySensorEntity(XEntity, BaseEntity, RestoreEntity): def set_state(self, data: dict): val = data.get(self.attr) if val is None: diff --git a/custom_components/xiaomi_miot/core/converters.py b/custom_components/xiaomi_miot/core/converters.py index f939d8189b..26b60030c3 100644 --- a/custom_components/xiaomi_miot/core/converters.py +++ b/custom_components/xiaomi_miot/core/converters.py @@ -14,6 +14,9 @@ class BaseConv: mi: str | int = None option: dict = None + def __post_init__(self): + self.option = {} + # to hass def decode(self, device: 'Device', payload: dict, value): payload[self.attr] = value @@ -32,7 +35,21 @@ def encode(self, device: 'Device', payload: dict, value): @dataclass class MiotPropConv(BaseConv): prop: 'MiotProperty' = None + desc: bool = False def __post_init__(self): + super().__post_init__() if not self.mi: self.mi = MiotSpec.unique_prop(self.prop.siid, piid=self.prop.iid) + + def decode(self, device: 'Device', payload: dict, value): + if self.desc: + payload['property_value'] = value + value = self.prop.list_description(value) + super().decode(device, payload, value) + + # from hass + def encode(self, device: 'Device', payload: dict, value): + if self.desc: + value = self.prop.list_value(value) + super().encode(device, payload, value) diff --git a/custom_components/xiaomi_miot/core/device.py b/custom_components/xiaomi_miot/core/device.py index 1a848a58d9..0d4cd31570 100644 --- a/custom_components/xiaomi_miot/core/device.py +++ b/custom_components/xiaomi_miot/core/device.py @@ -242,7 +242,8 @@ def init_converters(self): if not pls: continue for prop in self.spec.get_properties(*pls): - self.converters.append(MiotPropConv(prop.full_name, d, prop=prop)) + desc = prop.value_list and d in ['sensor', 'select'] + self.converters.append(MiotPropConv(prop.full_name, d, prop=prop, desc=desc)) def add_entity(self, entity: 'XEntity'): if entity not in self.entities: diff --git a/custom_components/xiaomi_miot/core/hass_entity.py b/custom_components/xiaomi_miot/core/hass_entity.py index 87b17b044b..adec0f35a3 100644 --- a/custom_components/xiaomi_miot/core/hass_entity.py +++ b/custom_components/xiaomi_miot/core/hass_entity.py @@ -118,10 +118,14 @@ def on_init(self): def on_device_update(self, data: dict): state_change = False - if self.listen_attrs & data.keys(): + if keys := self.listen_attrs & data.keys(): self.set_state(data) state_change = True self._attr_available = True + for key in keys: + if key == self.attr: + continue + self._attr_extra_state_attributes[key] = data.get(key) if state_change and self.added: self._async_write_ha_state() diff --git a/custom_components/xiaomi_miot/select.py b/custom_components/xiaomi_miot/select.py index 07ff6fc5c7..d404229cb1 100644 --- a/custom_components/xiaomi_miot/select.py +++ b/custom_components/xiaomi_miot/select.py @@ -3,14 +3,16 @@ from homeassistant.components.select import ( DOMAIN as ENTITY_DOMAIN, - SelectEntity, + SelectEntity as BaseEntity, ) +from homeassistant.helpers.restore_state import RestoreEntity from . import ( DOMAIN, CONF_MODEL, XIAOMI_CONFIG_SCHEMA as PLATFORM_SCHEMA, # noqa: F401 HassEntry, + XEntity, MiotEntity, BaseSubEntity, MiotPropertySubEntity, @@ -53,7 +55,26 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= bind_services_to_entries(hass, SERVICE_TO_METHOD) -class MiotSelectEntity(MiotEntity, SelectEntity): +class SelectEntity(XEntity, BaseEntity, RestoreEntity): + def on_init(self): + if self._miot_property: + self.listen_attrs.add('property_value') + self._attr_options = self._miot_property.list_descriptions() + + def get_state(self) -> dict: + return {self.attr: self._attr_current_option} + + def set_state(self, data: dict): + val = data.get(self.attr) + self._attr_current_option = val + + async def async_select_option(self, option: str): + await self.device.async_write({self.attr: option}) + +XEntity.CLS[ENTITY_DOMAIN] = SelectEntity + + +class MiotSelectEntity(MiotEntity, BaseEntity): def __init__(self, config, miot_service: MiotService): super().__init__(miot_service, config=config, logger=_LOGGER) self._attr_current_option = None @@ -93,7 +114,7 @@ def select_option(self, option): return ret -class MiotSelectSubEntity(SelectEntity, MiotPropertySubEntity): +class MiotSelectSubEntity(BaseEntity, MiotPropertySubEntity): def __init__(self, parent, miot_property: MiotProperty, option=None): MiotPropertySubEntity.__init__(self, parent, miot_property, option, domain=ENTITY_DOMAIN) self._attr_options = miot_property.list_descriptions() @@ -161,7 +182,7 @@ def select_option(self, option): return ret -class SelectSubEntity(SelectEntity, BaseSubEntity): +class SelectSubEntity(BaseEntity, BaseSubEntity): def __init__(self, parent, attr, option=None): BaseSubEntity.__init__(self, parent, attr, option) self._available = True diff --git a/custom_components/xiaomi_miot/sensor.py b/custom_components/xiaomi_miot/sensor.py index 4aed5c2a55..c0c331f641 100644 --- a/custom_components/xiaomi_miot/sensor.py +++ b/custom_components/xiaomi_miot/sensor.py @@ -141,9 +141,10 @@ def datetime_with_tzinfo(value): return value -class SensorEntity(XEntity, BaseEntity): +class SensorEntity(XEntity, BaseEntity, RestoreEntity): def on_init(self): if self._miot_property: + self.listen_attrs.add('property_value') self._attr_icon = self._miot_property.entity_icon self._attr_device_class = self._miot_property.device_class self._attr_native_unit_of_measurement = self._miot_property.unit_of_measurement