feat: update prop.format_ logic

This commit is contained in:
topsworld 2025-01-09 15:04:23 +08:00
parent d25d3f6a93
commit 93f04b1aee
5 changed files with 36 additions and 29 deletions

View File

@ -96,7 +96,7 @@ class Light(MIoTServiceEntity, LightEntity):
"""Light entities for Xiaomi Home."""
# pylint: disable=unused-argument
_VALUE_RANGE_MODE_COUNT_MAX = 30
_prop_on: Optional[MIoTSpecProperty]
_prop_on: MIoTSpecProperty
_prop_brightness: Optional[MIoTSpecProperty]
_prop_color_temp: Optional[MIoTSpecProperty]
_prop_color: Optional[MIoTSpecProperty]
@ -253,7 +253,7 @@ class Light(MIoTServiceEntity, LightEntity):
result: bool = False
# on
# Dirty logic for lumi.gateway.mgl03 indicator light
value_on = True if self._prop_on.format_ == 'bool' else 1
value_on = True if self._prop_on.format_ == bool else 1
result = await self.set_property_async(
prop=self._prop_on, value=value_on)
# brightness
@ -288,5 +288,5 @@ class Light(MIoTServiceEntity, LightEntity):
async def async_turn_off(self, **kwargs) -> None:
"""Turn the light off."""
# Dirty logic for lumi.gateway.mgl03 indicator light
value_on = False if self._prop_on.format_ == 'bool' else 0
value_on = False if self._prop_on.format_ == bool else 0
return await self.set_property_async(prop=self._prop_on, value=value_on)

View File

@ -513,7 +513,7 @@ class MIoTDevice:
if prop_access != (SPEC_PROP_TRANS_MAP[
'entities'][platform]['access']):
return None
if prop.format_ not in SPEC_PROP_TRANS_MAP[
if prop.format_.__name__ not in SPEC_PROP_TRANS_MAP[
'entities'][platform]['format']:
return None
if prop.unit:
@ -566,9 +566,9 @@ class MIoTDevice:
# general conversion
if not prop.platform:
if prop.writable:
if prop.format_ == 'str':
if prop.format_ == str:
prop.platform = 'text'
elif prop.format_ == 'bool':
elif prop.format_ == bool:
prop.platform = 'switch'
prop.device_class = SwitchDeviceClass.SWITCH
elif prop.value_list:

View File

@ -48,7 +48,7 @@ MIoT-Spec-V2 parser.
import asyncio
import platform
import time
from typing import Any, Optional, Union
from typing import Any, Optional, Type, Union
import logging
from slugify import slugify
@ -506,10 +506,10 @@ class _MIoTSpecBase:
class MIoTSpecProperty(_MIoTSpecBase):
"""MIoT SPEC property class."""
format_: str
unit: Optional[str]
precision: int
_format_: Type
_value_range: Optional[MIoTSpecValueRange]
_value_list: Optional[MIoTSpecValueList]
@ -543,6 +543,19 @@ class MIoTSpecProperty(_MIoTSpecBase):
self.spec_id = hash(
f'p.{self.name}.{self.service.iid}.{self.iid}')
@property
def format_(self) -> Type:
return self._format_
@format_.setter
def format_(self, value: str) -> None:
self._format_ = {
'string': str,
'str': str,
'bool': bool,
'float': float}.get(
value, int)
@property
def access(self) -> list:
return self._access
@ -601,11 +614,11 @@ class MIoTSpecProperty(_MIoTSpecBase):
def value_format(self, value: Any) -> Any:
if value is None:
return None
if self.format_ == 'int':
if self.format_ == int:
return int(value)
if self.format_ == 'float':
if self.format_ == float:
return round(value, self.precision)
if self.format_ == 'bool':
if self.format_ == bool:
return bool(value in [True, 1, 'True', 'true', '1'])
return value
@ -618,7 +631,7 @@ class MIoTSpecProperty(_MIoTSpecBase):
'description_trans': self.description_trans,
'proprietary': self.proprietary,
'need_filter': self.need_filter,
'format': self.format_,
'format': self.format_.__name__,
'access': self._access,
'unit': self.unit,
'value_range': (
@ -1048,12 +1061,6 @@ class MIoTSpecParser:
return await self._storage.save_async(
domain=self._DOMAIN, name=f'{urn}_{self._lang}', data=data)
def __spec_format2dtype(self, format_: str) -> str:
# 'string'|'bool'|'uint8'|'uint16'|'uint32'|
# 'int8'|'int16'|'int32'|'int64'|'float'
return {'string': 'str', 'bool': 'bool', 'float': 'float'}.get(
format_, 'int')
async def __get_instance(self, urn: str) -> Optional[dict]:
return await MIoTHttp.get_json_async(
url='https://miot-spec.org/miot-spec-v2/instance',
@ -1124,7 +1131,7 @@ class MIoTSpecParser:
spec_prop: MIoTSpecProperty = MIoTSpecProperty(
spec=property_,
service=spec_service,
format_=self.__spec_format2dtype(property_['format']),
format_=property_['format'],
access=property_['access'],
unit=property_.get('unit', None))
spec_prop.name = p_type_strs[3]

View File

@ -90,7 +90,7 @@ class Notify(MIoTActionEntity, NotifyEntity):
super().__init__(miot_device=miot_device, spec=spec)
self._attr_extra_state_attributes = {}
action_in: str = ', '.join([
f'{prop.description_trans}({prop.format_})'
f'{prop.description_trans}({prop.format_.__name__})'
for prop in self.spec.in_])
self._attr_extra_state_attributes['action params'] = f'[{action_in}]'
@ -122,24 +122,24 @@ class Notify(MIoTActionEntity, NotifyEntity):
return
in_value: list[dict] = []
for index, prop in enumerate(self.spec.in_):
if prop.format_ == 'str':
if prop.format_ == str:
if isinstance(in_list[index], (bool, int, float, str)):
in_value.append(
{'piid': prop.iid, 'value': str(in_list[index])})
continue
elif prop.format_ == 'bool':
elif prop.format_ == bool:
if isinstance(in_list[index], (bool, int)):
# yes, no, on, off, true, false and other bool types
# will also be parsed as 0 and 1 of int.
in_value.append(
{'piid': prop.iid, 'value': bool(in_list[index])})
continue
elif prop.format_ == 'float':
elif prop.format_ == float:
if isinstance(in_list[index], (int, float)):
in_value.append(
{'piid': prop.iid, 'value': in_list[index]})
continue
elif prop.format_ == 'int':
elif prop.format_ == int:
if isinstance(in_list[index], int):
in_value.append(
{'piid': prop.iid, 'value': in_list[index]})

View File

@ -111,7 +111,7 @@ class ActionText(MIoTActionEntity, TextEntity):
self._attr_extra_state_attributes = {}
self._attr_native_value = ''
action_in: str = ', '.join([
f'{prop.description_trans}({prop.format_})'
f'{prop.description_trans}({prop.format_.__name__})'
for prop in self.spec.in_])
self._attr_extra_state_attributes['action params'] = f'[{action_in}]'
# For action debug
@ -141,24 +141,24 @@ class ActionText(MIoTActionEntity, TextEntity):
f'invalid action params, {value}')
in_value: list[dict] = []
for index, prop in enumerate(self.spec.in_):
if prop.format_ == 'str':
if prop.format_ == str:
if isinstance(in_list[index], (bool, int, float, str)):
in_value.append(
{'piid': prop.iid, 'value': str(in_list[index])})
continue
elif prop.format_ == 'bool':
elif prop.format_ == bool:
if isinstance(in_list[index], (bool, int)):
# yes, no, on, off, true, false and other bool types
# will also be parsed as 0 and 1 of int.
in_value.append(
{'piid': prop.iid, 'value': bool(in_list[index])})
continue
elif prop.format_ == 'float':
elif prop.format_ == float:
if isinstance(in_list[index], (int, float)):
in_value.append(
{'piid': prop.iid, 'value': in_list[index]})
continue
elif prop.format_ == 'int':
elif prop.format_ == int:
if isinstance(in_list[index], int):
in_value.append(
{'piid': prop.iid, 'value': in_list[index]})