Skip to content

Commit 69ee33b

Browse files
committed
🔧 fix for sensor_attributes (#1562)
1 parent cebfe10 commit 69ee33b

File tree

4 files changed

+60
-57
lines changed

4 files changed

+60
-57
lines changed

custom_components/xiaomi_miot/__init__.py

Lines changed: 51 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,7 +1044,7 @@ async def async_update(self):
10441044
self._state = attrs.get('power') == 'on'
10451045
await self.async_update_attrs(attrs)
10461046

1047-
def _update_attr_sensor_entities(self, attrs, domain='sensor', option=None):
1047+
async def async_update_attr_sensor_entities(self, attrs, domain='sensor', option=None):
10481048
add_sensors = self._add_entities.get(domain)
10491049
opt = {**(option or {})}
10501050
for a in attrs:
@@ -1056,6 +1056,8 @@ def _update_attr_sensor_entities(self, attrs, domain='sensor', option=None):
10561056
opt['dict_key'] = kys[1]
10571057
if a not in self._state_attrs:
10581058
continue
1059+
if not add_sensors:
1060+
continue
10591061
tms = self._check_same_sub_entity(p, domain)
10601062
if p in self._subs:
10611063
self._subs[p].update_from_parent()
@@ -1064,8 +1066,6 @@ def _update_attr_sensor_entities(self, attrs, domain='sensor', option=None):
10641066
if tms <= 1:
10651067
self.logger.info('%s: Device sub entity %s: %s already exists.', self.name_model, domain, p)
10661068
continue
1067-
elif not add_sensors:
1068-
pass
10691069
elif domain == 'sensor':
10701070
from .sensor import BaseSensorSubEntity
10711071
option = {'unique_id': f'{self._unique_did}-{p}', **opt}
@@ -1101,35 +1101,34 @@ def turn_off(self, **kwargs):
11011101

11021102
def update_attrs(self, attrs: dict, update_parent=False, update_subs=True):
11031103
self._state_attrs.update(attrs or {})
1104-
if self.hass and self.platform and update_subs:
1105-
tps = cv.ensure_list(self.custom_config('attributes_template'))
1106-
for tpl in tps:
1107-
if not tpl:
1108-
continue
1109-
tpl = CUSTOM_TEMPLATES.get(tpl, tpl)
1110-
tpl = cv.template(tpl)
1111-
tpl.hass = self.hass
1112-
adt = tpl.render({'data': self._state_attrs}) or {}
1113-
if isinstance(adt, dict):
1114-
if adt.pop('_override', False):
1115-
self._state_attrs = adt
1116-
else:
1117-
self._state_attrs.update(adt)
11181104
if update_parent and hasattr(self, '_parent'):
11191105
if self._parent and hasattr(self._parent, 'update_attrs'):
11201106
getattr(self._parent, 'update_attrs')(attrs or {}, update_parent=False)
1107+
return self._state_attrs
1108+
1109+
async def async_update_attrs(self, attrs: dict, update_parent=False, update_subs=True):
1110+
self._state_attrs.update(attrs or {})
11211111
if update_subs:
1112+
if self.hass and self.platform:
1113+
tps = cv.ensure_list(self.custom_config('attributes_template'))
1114+
for tpl in tps:
1115+
if not tpl:
1116+
continue
1117+
tpl = CUSTOM_TEMPLATES.get(tpl, tpl)
1118+
tpl = cv.template(tpl)
1119+
tpl.hass = self.hass
1120+
adt = tpl.async_render({'data': self._state_attrs}) or {}
1121+
if isinstance(adt, dict):
1122+
if adt.pop('_override', False):
1123+
self._state_attrs = adt
1124+
else:
1125+
self._state_attrs.update(adt)
11221126
if pls := self.custom_config_list('sensor_attributes'):
1123-
self._update_attr_sensor_entities(pls, domain='sensor')
1127+
await self.async_update_attr_sensor_entities(pls, domain='sensor')
11241128
if pls := self.custom_config_list('binary_sensor_attributes'):
1125-
self._update_attr_sensor_entities(pls, domain='binary_sensor')
1129+
await self.async_update_attr_sensor_entities(pls, domain='binary_sensor')
11261130
return self._state_attrs
11271131

1128-
async def async_update_attrs(self, *args, **kwargs):
1129-
return await self.hass.async_add_executor_job(
1130-
partial(self.update_attrs, *args, **kwargs)
1131-
)
1132-
11331132

11341133
class MiotEntityInterface:
11351134
_miot_service = None
@@ -1600,10 +1599,10 @@ async def async_update_for_main_entity(self):
16001599

16011600
# update miio prop/event in cloud
16021601
if cls := self.custom_config_list('miio_cloud_records'):
1603-
await self.hass.async_add_executor_job(partial(self.update_miio_cloud_records, cls))
1602+
await self.async_update_miio_cloud_records(pls)
16041603

16051604
if pls := self.custom_config_list('miio_cloud_props'):
1606-
await self.hass.async_add_executor_job(partial(self.update_miio_cloud_props, pls))
1605+
await self.async_update_miio_cloud_props(pls)
16071606

16081607
# update micloud statistics in cloud
16091608
cls = self.custom_config_list('micloud_statistics') or []
@@ -1618,38 +1617,40 @@ async def async_update_for_main_entity(self):
16181617
}
16191618
cls = [*cls, dic]
16201619
if cls:
1621-
await self.hass.async_add_executor_job(partial(self.update_micloud_statistics, cls))
1620+
await self.async_update_micloud_statistics(cls)
16221621

16231622
# update miio properties in lan
16241623
if pls := self._vars.get('miio_properties', []):
1625-
await self.hass.async_add_executor_job(partial(self.update_miio_props, pls))
1624+
await self.async_update_miio_props(pls)
16261625

16271626
# update miio commands in lan
16281627
if cls := self.custom_config_json('miio_commands'):
1629-
await self.hass.async_add_executor_job(partial(self.update_miio_commands, cls))
1628+
await self.async_update_miio_commands(cls)
16301629

1631-
def update_miio_props(self, props):
1630+
async def async_update_miio_props(self, props):
16321631
if not self.miot_device:
16331632
return
16341633
if self._miio2miot:
16351634
attrs = self._miio2miot.only_miio_props(props)
16361635
else:
16371636
try:
16381637
num = self.custom_config_integer('chunk_properties') or 15
1639-
attrs = self._device.get_properties(props, max_properties=num)
1638+
attrs = await self.hass.async_add_executor_job(
1639+
partial(self._device.get_properties, props, max_properties=num)
1640+
)
16401641
except DeviceException as exc:
16411642
self.logger.warning('%s: Got miio properties %s failed: %s', self.name_model, props, exc)
16421643
return
16431644
if len(props) != len(attrs):
1644-
self.update_attrs({
1645+
await self.async_update_attrs({
16451646
'miio.props': attrs,
16461647
})
16471648
return
16481649
attrs = dict(zip(map(lambda x: f'miio.{x}', props), attrs))
16491650
self.logger.debug('%s: Got miio properties: %s', self.name_model, attrs)
1650-
self.update_attrs(attrs)
1651+
await self.async_update_attrs(attrs)
16511652

1652-
def update_miio_commands(self, commands):
1653+
async def async_update_miio_commands(self, commands):
16531654
if not self.miot_device:
16541655
return
16551656
if isinstance(commands, dict):
@@ -1663,7 +1664,9 @@ def update_miio_commands(self, commands):
16631664
cmd = cfg.get('method')
16641665
pms = cfg.get('params') or []
16651666
try:
1666-
attrs = self._device.send(cmd, pms)
1667+
attrs = await self.hass.async_add_executor_job(
1668+
partial(self._device.send, cmd, pms)
1669+
)
16671670
except DeviceException as exc:
16681671
self.logger.warning('%s: Send miio command %s(%s) failed: %s', self.name_model, cmd, cfg, exc)
16691672
continue
@@ -1675,9 +1678,9 @@ def update_miio_commands(self, commands):
16751678
else:
16761679
attrs = dict(zip(props, attrs))
16771680
self.logger.debug('%s: Got miio properties: %s', self.name_model, attrs)
1678-
self.update_attrs(attrs)
1681+
await self.async_update_attrs(attrs)
16791682

1680-
def update_miio_cloud_props(self, keys):
1683+
async def async_update_miio_cloud_props(self, keys):
16811684
did = str(self.miot_did)
16821685
mic = self.xiaomi_cloud
16831686
if not did or not mic:
@@ -1691,7 +1694,7 @@ def update_miio_cloud_props(self, keys):
16911694
'did': did,
16921695
'props': kls,
16931696
}
1694-
rdt = mic.request_miot_api('device/batchdevicedatas', [pms]) or {}
1697+
rdt = await mic.async_request_api('device/batchdevicedatas', [pms]) or {}
16951698
self.logger.debug('%s: Got miio cloud props: %s', self.name_model, rdt)
16961699
props = (rdt.get('result') or {}).get(did, {})
16971700

@@ -1700,12 +1703,12 @@ def update_miio_cloud_props(self, keys):
17001703
tpl = CUSTOM_TEMPLATES.get(tpl, tpl)
17011704
tpl = cv.template(tpl)
17021705
tpl.hass = self.hass
1703-
attrs = tpl.render({'props': props})
1706+
attrs = tpl.async_render({'props': props})
17041707
else:
17051708
attrs = props
1706-
self.update_attrs(attrs)
1709+
await self.async_update_attrs(attrs)
17071710

1708-
def update_miio_cloud_records(self, keys):
1711+
async def async_update_miio_cloud_records(self, keys):
17091712
did = self.miot_did
17101713
mic = self.xiaomi_cloud
17111714
if not did or not mic:
@@ -1723,13 +1726,13 @@ def update_miio_cloud_records(self, keys):
17231726
}
17241727
if gby:
17251728
kws['group'] = gby
1726-
rdt = mic.get_user_device_data(did, key, typ, **kws) or []
1729+
rdt = await mic.async_get_user_device_data(did, key, typ, **kws) or []
17271730
tpl = self.custom_config(f'miio_{typ}_{key}_template')
17281731
if tpl:
17291732
tpl = CUSTOM_TEMPLATES.get(tpl, tpl)
17301733
tpl = cv.template(tpl)
17311734
tpl.hass = self.hass
1732-
rls = tpl.render({'result': rdt})
1735+
rls = tpl.async_render({'result': rdt})
17331736
else:
17341737
rls = [
17351738
v.get('value')
@@ -1741,9 +1744,9 @@ def update_miio_cloud_records(self, keys):
17411744
else:
17421745
attrs[f'{typ}.{key}'] = rls
17431746
if attrs:
1744-
self.update_attrs(attrs)
1747+
await self.async_update_attrs(attrs)
17451748

1746-
def update_micloud_statistics(self, lst):
1749+
async def async_update_micloud_statistics(self, lst):
17471750
did = self.miot_did
17481751
mic = self.xiaomi_cloud
17491752
if not did or not mic:
@@ -1762,14 +1765,14 @@ def update_micloud_statistics(self, lst):
17621765
'time_end': now + 60,
17631766
'limit': int(c.get('limit') or 1),
17641767
}
1765-
rdt = mic.request_miot_api('v2/user/statistics', pms) or {}
1768+
rdt = await mic.async_request_api('v2/user/statistics', pms) or {}
17661769
self.logger.debug('%s: Got micloud statistics: %s', self.name_model, rdt)
17671770
tpl = c.get('template')
17681771
if tpl:
17691772
tpl = CUSTOM_TEMPLATES.get(tpl, tpl)
17701773
tpl = cv.template(tpl)
17711774
tpl.hass = self.hass
1772-
rls = tpl.render(rdt)
1775+
rls = tpl.async_render(rdt)
17731776
else:
17741777
rls = [
17751778
v.get('value')
@@ -1781,7 +1784,7 @@ def update_micloud_statistics(self, lst):
17811784
elif isinstance(rls, dict):
17821785
attrs.update(rls)
17831786
if attrs:
1784-
self.update_attrs(attrs)
1787+
await self.async_update_attrs(attrs)
17851788

17861789
def get_properties(self, mapping, update_entity=False, throw=False, **kwargs):
17871790
results = []

custom_components/xiaomi_miot/binary_sensor.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -343,12 +343,7 @@ async def async_update(self):
343343
if isinstance(mic, MiotCloud):
344344
now = int(time.time())
345345
ofs = self.custom_config_integer('time_start_offset') or -86400 * 3
346-
dlg = await self.hass.async_add_executor_job(partial(
347-
mic.get_last_device_data,
348-
self.miot_did,
349-
'device_log',
350-
time_start=now + ofs,
351-
))
346+
dlg = await mic.async_get_last_device_data(self.miot_did, 'device_log', time_start=now + ofs)
352347
pes = json.loads(dlg or '[]')
353348
adt = {}
354349
typ = None

custom_components/xiaomi_miot/core/xiaomi_cloud.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ def request_miot_spec(self, api, params=None):
100100
raise MiCloudException(json.dumps(rdt))
101101
return rls
102102

103+
async def async_get_user_device_data(self, *args, **kwargs):
104+
return await self.hass.async_add_executor_job(
105+
partial(self.get_user_device_data, *args, **kwargs)
106+
)
107+
103108
def get_user_device_data(self, did, key, typ='prop', raw=False, **kwargs):
104109
now = int(time.time())
105110
timeout = kwargs.pop('timeout', self.http_timeout)
@@ -115,10 +120,10 @@ def get_user_device_data(self, did, key, typ='prop', raw=False, **kwargs):
115120
rdt = self.request_miot_api('user/get_user_device_data', params, timeout=timeout) or {}
116121
return rdt if raw else rdt.get('result')
117122

118-
def get_last_device_data(self, did, key, typ='prop', **kwargs):
123+
async def async_get_last_device_data(self, did, key, typ='prop', **kwargs):
119124
kwargs['raw'] = False
120125
kwargs['limit'] = 1
121-
rls = self.get_user_device_data(did, key, typ, **kwargs) or [None]
126+
rls = await self.async_get_user_device_data(did, key, typ, **kwargs) or [None]
122127
rdt = rls.pop(0) or {}
123128
if kwargs.get('not_value'):
124129
return rdt

custom_components/xiaomi_miot/vacuum.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ async def async_update(self):
387387
if not self._available:
388388
return
389389
if self._miio2miot:
390-
await self.hass.async_add_executor_job(partial(self.update_miio_props, self._miio_props))
390+
await self.async_update_miio_props(self._miio_props)
391391
props = self._state_attrs or {}
392392
adt = {}
393393
if 'miio.s_area' in props:

0 commit comments

Comments
 (0)