From e6750bb7467551758d8644d594184098a5456779 Mon Sep 17 00:00:00 2001 From: Li Shuzhen Date: Tue, 25 Nov 2025 09:31:40 +0800 Subject: [PATCH] feat: format value, then evaluate by expression, and set precision at last (#1516) --- .../xiaomi_home/miot/miot_device.py | 15 +++++++++++---- .../xiaomi_home/miot/miot_spec.py | 18 ++++++++++++++---- custom_components/xiaomi_home/sensor.py | 2 +- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/custom_components/xiaomi_home/miot/miot_device.py b/custom_components/xiaomi_home/miot/miot_device.py index a0e2edb..a585800 100644 --- a/custom_components/xiaomi_home/miot/miot_device.py +++ b/custom_components/xiaomi_home/miot/miot_device.py @@ -1041,6 +1041,7 @@ class MIoTServiceEntity(Entity): f'set property failed, property is None, ' f'{self.entity_id}, {self.name}') value = prop.value_format(value) + value = prop.value_precision(value) if prop not in self.entity_data.props: raise RuntimeError( f'set property failed, unknown property, ' @@ -1078,9 +1079,11 @@ class MIoTServiceEntity(Entity): 'get property failed, not readable, %s, %s, %s', self.entity_id, self.name, prop.name) return None - result = prop.value_format( + value: Any = prop.value_format( await self.miot_device.miot_client.get_prop_async( did=self.miot_device.did, siid=prop.service.iid, piid=prop.iid)) + value = prop.eval_expr(value) + result = prop.value_precision(value) if result != self._prop_value_map[prop]: self._prop_value_map[prop] = result self.async_write_ha_state() @@ -1111,7 +1114,7 @@ class MIoTServiceEntity(Entity): continue value: Any = prop.value_format(params['value']) value = prop.eval_expr(value) - value = prop.value_format(value) + value = prop.value_precision(value) self._prop_value_map[prop] = value if prop in self._prop_changed_subs: self._prop_changed_subs[prop](prop, value) @@ -1259,6 +1262,7 @@ class MIoTPropertyEntity(Entity): f'set property failed, not writable, ' f'{self.entity_id}, {self.name}') value = self.spec.value_format(value) + value = self.spec.value_precision(value) try: await self.miot_device.miot_client.set_prop_async( did=self.miot_device.did, siid=self.spec.service.iid, @@ -1276,16 +1280,19 @@ class MIoTPropertyEntity(Entity): 'get property failed, not readable, %s, %s', self.entity_id, self.name) return None - return self.spec.value_format( + value: Any = self.spec.value_format( await self.miot_device.miot_client.get_prop_async( did=self.miot_device.did, siid=self.spec.service.iid, piid=self.spec.iid)) + value = self.spec.eval_expr(value) + result = self.spec.value_precision(value) + return result def __on_value_changed(self, params: dict, ctx: Any) -> None: _LOGGER.debug('property changed, %s', params) value: Any = self.spec.value_format(params['value']) value = self.spec.eval_expr(value) - self._value = self.spec.value_format(value) + self._value = self.spec.value_precision(value) if not self._pending_write_ha_state_timer: self.async_write_ha_state() diff --git a/custom_components/xiaomi_home/miot/miot_spec.py b/custom_components/xiaomi_home/miot/miot_spec.py index cd61887..0f7da5e 100644 --- a/custom_components/xiaomi_home/miot/miot_spec.py +++ b/custom_components/xiaomi_home/miot/miot_spec.py @@ -599,15 +599,25 @@ class MIoTSpecProperty(_MIoTSpecBase): def value_format(self, value: Any) -> Any: if value is None: return None + if isinstance(value, str): + if self.format_ == int: + value = int(float(value)) + elif self.format_ == float: + value = float(value) + if self.format_ == bool: + return bool(value in [True, 1, 'True', 'true', '1']) + return value + + def value_precision(self, value: Any) -> Any: + if value is None: + return None + if self.format_ == float: + return round(value, self.precision) if self.format_ == int: if self.value_range is None: return int(round(value)) return int( round(value / self.value_range.step) * self.value_range.step) - if self.format_ == float: - return round(value, self.precision) - if self.format_ == bool: - return bool(value in [True, 1, 'True', 'true', '1']) return value def dump(self) -> dict: diff --git a/custom_components/xiaomi_home/sensor.py b/custom_components/xiaomi_home/sensor.py index 88cb063..02371c9 100644 --- a/custom_components/xiaomi_home/sensor.py +++ b/custom_components/xiaomi_home/sensor.py @@ -110,7 +110,7 @@ class Sensor(MIoTPropertyEntity, SensorEntity): self._attr_native_unit_of_measurement = list( unit_sets)[0] if unit_sets else None # Set suggested precision - if spec.format_ in {int, float} and spec.expr is None: + if spec.format_ == float: self._attr_suggested_display_precision = spec.precision # Set state_class if spec.state_class: