Fixed device_get and device_rename to use the new zigbee2mqtt API

This commit is contained in:
Fabio Manganiello 2021-02-08 01:45:21 +01:00
parent 452533db17
commit 15d2e1116b

View file

@ -124,6 +124,10 @@ class ZigbeeMqttPlugin(MqttPlugin):
self.base_topic = base_topic self.base_topic = base_topic
self.timeout = timeout self.timeout = timeout
self._info = {
'devices': {},
'groups': {},
}
def _get_network_info(self, **kwargs): def _get_network_info(self, **kwargs):
self.logger.info('Fetching Zigbee network information') self.logger.info('Fetching Zigbee network information')
@ -166,6 +170,18 @@ class ZigbeeMqttPlugin(MqttPlugin):
if not info_ready: if not info_ready:
raise TimeoutError('A timeout occurred while fetching the Zigbee network information') raise TimeoutError('A timeout occurred while fetching the Zigbee network information')
# Cache the new results
self._info['devices'] = {
device.get('friendly_name', device['ieee_address']): device
for device in info.get('devices', [])
}
self._info['groups'] = {
group.get('name'): group
for group in info.get('groups', [])
}
self.logger.info('Zigbee network configuration updated')
return info return info
finally: finally:
try: try:
@ -174,21 +190,18 @@ class ZigbeeMqttPlugin(MqttPlugin):
except Exception as e: except Exception as e:
self.logger.warning('Error on MQTT client disconnection: {}'.format(str(e))) self.logger.warning('Error on MQTT client disconnection: {}'.format(str(e)))
def _mqtt_args(self, host: Optional[str] = None, **kwargs): def _mqtt_args(self, **kwargs):
if not host: return {
return { 'host': kwargs.get('host', self.host),
'host': self.host, 'port': kwargs.get('port', self.port),
'port': self.port, 'timeout': kwargs.get('timeout', self.timeout),
'timeout': self.timeout, 'tls_certfile': kwargs.get('tls_certfile', self.tls_certfile),
'tls_certfile': self.tls_certfile, 'tls_keyfile': kwargs.get('tls_keyfile', self.tls_keyfile),
'tls_keyfile': self.tls_keyfile, 'tls_version': kwargs.get('tls_version', self.tls_version),
'tls_version': self.tls_version, 'tls_ciphers': kwargs.get('tls_ciphers', self.tls_ciphers),
'tls_ciphers': self.tls_ciphers, 'username': kwargs.get('username', self.username),
'username': self.username, 'password': kwargs.get('password', self.password),
'password': self.password, }
}
return kwargs
def _topic(self, topic): def _topic(self, topic):
return self.base_topic + '/' + topic return self.base_topic + '/' + topic
@ -497,10 +510,45 @@ class ZigbeeMqttPlugin(MqttPlugin):
assert not [dev for dev in devices if dev.get('friendly_name') == name], \ assert not [dev for dev in devices if dev.get('friendly_name') == name], \
'A device named {} already exists on the network'.format(name) 'A device named {} already exists on the network'.format(name)
if device:
req = {
'from': device,
'to': name,
}
else:
req = {
'last': True,
'to': name,
}
self.publish( self.publish(
topic=self._topic('bridge/config/rename{}'.format('_last' if not device else '')), topic=self._topic('bridge/request/device/rename'),
msg={'old': device, 'new': name} if device else name, msg=req, **self._mqtt_args(**kwargs))
**self._mqtt_args(**kwargs))
@staticmethod
def _build_device_get_request(values: List[Dict[str, Any]]) -> dict:
def extract_value(value: dict, root: dict):
if not value.get('access', 1) & 0x1:
# Property not readable
return
if 'features' not in value:
if 'property' in value:
root[value['property']] = ''
return
if 'property' in value:
root[value['property']] = root.get(value['property'], {})
root = root[value['property']]
for feature in value['features']:
extract_value(feature, root)
ret = {}
for value in values:
extract_value(value, root=ret)
return ret
# noinspection PyShadowingBuiltins # noinspection PyShadowingBuiltins
@action @action
@ -516,16 +564,26 @@ class ZigbeeMqttPlugin(MqttPlugin):
(default: query the default configured device). (default: query the default configured device).
:return: Key->value map of the device properties. :return: Key->value map of the device properties.
""" """
properties = self.publish(topic=self._topic(device + ('/get' if property else '')), kwargs = self._mqtt_args(**kwargs)
reply_topic=self._topic(device),
msg={property: ''} if property else '',
**self._mqtt_args(**kwargs)).output
if property: if property:
properties = self.publish(topic=self._topic(device) + '/get/' + property, reply_topic=self._topic(device),
msg={property: ''}, **kwargs).output
assert property in properties, 'No such property: ' + property assert property in properties, 'No such property: ' + property
return {property: properties[property]} return {property: properties[property]}
return properties if device not in self._info.get('devices', {}):
# Refresh devices info
self._get_network_info(**kwargs)
assert self._info.get('devices', {}).get(device), 'No such device: ' + device
exposes = (self._info.get('devices', {}).get(device, {}).get('definition', {}) or {}).get('exposes', [])
if not exposes:
return {}
return self.publish(topic=self._topic(device) + '/get', reply_topic=self._topic(device),
msg=self._build_device_get_request(exposes), **kwargs)
# noinspection PyShadowingBuiltins,DuplicatedCode # noinspection PyShadowingBuiltins,DuplicatedCode
@action @action