From 5adcb7ce00953d55ccd94f33ea7833619884f9ce Mon Sep 17 00:00:00 2001 From: Li Shuzhen Date: Wed, 5 Mar 2025 15:31:02 +0800 Subject: [PATCH 1/3] fix: wind-reverse format type (#810) --- custom_components/xiaomi_home/fan.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/xiaomi_home/fan.py b/custom_components/xiaomi_home/fan.py index 0f64aa8..1d15c9b 100644 --- a/custom_components/xiaomi_home/fan.py +++ b/custom_components/xiaomi_home/fan.py @@ -172,7 +172,7 @@ class Fan(MIoTServiceEntity, FanEntity): self._attr_supported_features |= FanEntityFeature.OSCILLATE self._prop_horizontal_swing = prop elif prop.name == 'wind-reverse': - if prop.format_ == 'bool': + if prop.format_ == bool: self._prop_wind_reverse_forward = False self._prop_wind_reverse_reverse = True elif prop.value_list: @@ -186,7 +186,7 @@ class Fan(MIoTServiceEntity, FanEntity): or self._prop_wind_reverse_reverse is None ): # NOTICE: Value may be 0 or False - _LOGGER.info( + _LOGGER.error( 'invalid wind-reverse, %s', self.entity_id) continue self._attr_supported_features |= FanEntityFeature.DIRECTION From 79016076486e5a38adf65a5d162e5bc03c94585d Mon Sep 17 00:00:00 2001 From: Li Shuzhen Date: Wed, 5 Mar 2025 15:31:18 +0800 Subject: [PATCH 2/3] fix: fan-level without value-list but with value-range (#808) --- custom_components/xiaomi_home/miot/miot_spec.py | 11 +++++++++++ .../xiaomi_home/miot/specs/spec_modify.yaml | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/custom_components/xiaomi_home/miot/miot_spec.py b/custom_components/xiaomi_home/miot/miot_spec.py index 859453b..ebf1759 100644 --- a/custom_components/xiaomi_home/miot/miot_spec.py +++ b/custom_components/xiaomi_home/miot/miot_spec.py @@ -1205,6 +1205,13 @@ class _SpecModify: return None return value_range + def get_prop_value_list(self, siid: int, piid: int) -> Optional[list]: + value_list = self.__get_prop_item(siid=siid, piid=piid, + key='value-list') + if not isinstance(value_list, list): + return None + return value_list + def __get_prop_item(self, siid: int, piid: int, key: str) -> Optional[str]: if not self._selected: return None @@ -1485,6 +1492,10 @@ class MIoTSpecParser: siid=service['iid'], piid=property_['iid']) if custom_range: spec_prop.value_range = custom_range + custom_list = self._spec_modify.get_prop_value_list( + siid=service['iid'], piid=property_['iid']) + if custom_list: + spec_prop.value_list = custom_list # Parse service event for event in service.get('events', []): if ( diff --git a/custom_components/xiaomi_home/miot/specs/spec_modify.yaml b/custom_components/xiaomi_home/miot/specs/spec_modify.yaml index 131ef59..58ba8ef 100644 --- a/custom_components/xiaomi_home/miot/specs/spec_modify.yaml +++ b/custom_components/xiaomi_home/miot/specs/spec_modify.yaml @@ -49,3 +49,12 @@ urn:miot-spec-v2:device:airer:0000A00D:hyd-znlyj5:1: - 1 - 1 urn:miot-spec-v2:device:airer:0000A00D:hyd-znlyj5:2: urn:miot-spec-v2:device:airer:0000A00D:hyd-znlyj5:1 +urn:miot-spec-v2:device:bath-heater:0000A028:opple-acmoto:1: + prop.5.2: + value-list: + - value: 1 + description: low + - value: 128 + description: medium + - value: 255 + description: high From e69448f2ebeb86515f76f1834111171c0f7d943b Mon Sep 17 00:00:00 2001 From: Necroneco Date: Wed, 5 Mar 2025 16:13:17 +0800 Subject: [PATCH 3/3] feat: add entity_category for indicator-light (#697) --- .../xiaomi_home/miot/miot_device.py | 5 +++++ .../xiaomi_home/miot/miot_spec.py | 4 +++- .../xiaomi_home/miot/specs/specv2entity.py | 19 +++++++++++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/custom_components/xiaomi_home/miot/miot_device.py b/custom_components/xiaomi_home/miot/miot_device.py index 1f3f186..b91be48 100644 --- a/custom_components/xiaomi_home/miot/miot_device.py +++ b/custom_components/xiaomi_home/miot/miot_device.py @@ -549,6 +549,10 @@ class MIoTDevice: # Optional actions # Optional events miot_service.platform = platform + # entity_category + if entity_category := SPEC_SERVICE_TRANS_MAP[service_name].get( + 'entity_category', None): + miot_service.entity_category = entity_category return entity_data def parse_miot_property_entity(self, miot_prop: MIoTSpecProperty) -> bool: @@ -899,6 +903,7 @@ class MIoTServiceEntity(Entity): self._attr_name = ( f'{"* "if self.entity_data.spec.proprietary else " "}' f'{self.entity_data.spec.description_trans}') + self._attr_entity_category = entity_data.spec.entity_category # Set entity attr self._attr_unique_id = self.entity_id self._attr_should_poll = False diff --git a/custom_components/xiaomi_home/miot/miot_spec.py b/custom_components/xiaomi_home/miot/miot_spec.py index ebf1759..d2292e8 100644 --- a/custom_components/xiaomi_home/miot/miot_spec.py +++ b/custom_components/xiaomi_home/miot/miot_spec.py @@ -465,7 +465,7 @@ class _MIoTSpecBase: iid: int type_: str description: str - description_trans: str + description_trans: Optional[str] proprietary: bool need_filter: bool name: str @@ -476,6 +476,7 @@ class _MIoTSpecBase: device_class: Any state_class: Any external_unit: Any + entity_category: Optional[str] spec_id: int @@ -494,6 +495,7 @@ class _MIoTSpecBase: self.device_class = None self.state_class = None self.external_unit = None + self.entity_category = None self.spec_id = hash(f'{self.type_}.{self.iid}') diff --git a/custom_components/xiaomi_home/miot/specs/specv2entity.py b/custom_components/xiaomi_home/miot/specs/specv2entity.py index 82b2844..b3039de 100644 --- a/custom_components/xiaomi_home/miot/specs/specv2entity.py +++ b/custom_components/xiaomi_home/miot/specs/specv2entity.py @@ -51,6 +51,7 @@ from homeassistant.components.event import EventDeviceClass from homeassistant.const import ( CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + EntityCategory, LIGHT_LUX, UnitOfEnergy, UnitOfPower, @@ -330,7 +331,8 @@ SPEC_DEVICE_TRANS_MAP: dict = { 'events': set, 'actions': set }, - 'entity': str + 'entity': str, + 'entity_category'?: str } } """ @@ -348,10 +350,23 @@ SPEC_SERVICE_TRANS_MAP: dict = { }, 'entity': 'light' }, - 'indicator-light': 'light', 'ambient-light': 'light', 'night-light': 'light', 'white-light': 'light', + 'indicator-light': { + 'required': { + 'properties': { + 'on': {'read', 'write'} + } + }, + 'optional': { + 'properties': { + 'mode', 'brightness', + } + }, + 'entity': 'light', + 'entity_category': EntityCategory.CONFIG + }, 'fan': { 'required': { 'properties': {