Fixed device_get and device_rename to use the new zigbee2mqtt API
This commit is contained in:
parent
816492d3b2
commit
b8979040da
1 changed files with 81 additions and 23 deletions
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue