Support for battery sensors on zigbee.mqtt

This commit is contained in:
Fabio Manganiello 2022-10-29 18:15:45 +02:00
parent 42651e937b
commit 71ccf6d04a
Signed by: blacklight
GPG Key ID: D90FBA7F76362774
1 changed files with 99 additions and 53 deletions

View File

@ -169,7 +169,7 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
if not dev: if not dev:
continue continue
converted_entity = None converted_entities = []
dev_def = dev.get("definition") or {} dev_def = dev.get("definition") or {}
dev_info = { dev_info = {
"type": dev.get("type"), "type": dev.get("type"),
@ -186,64 +186,84 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
light_info = self._get_light_meta(dev) light_info = self._get_light_meta(dev)
switch_info = self._get_switch_meta(dev) switch_info = self._get_switch_meta(dev)
battery_info = self._get_battery_meta(dev)
if light_info: if light_info:
converted_entity = Light( converted_entities.append(
id=dev['ieee_address'], Light(
name=dev.get('friendly_name'), id=dev['ieee_address'],
on=dev.get('state', {}).get('state') == switch_info.get('value_on'), name=dev.get('friendly_name'),
brightness_min=light_info.get('brightness_min'), on=dev.get('state', {}).get('state')
brightness_max=light_info.get('brightness_max'), == switch_info.get('value_on'),
temperature_min=light_info.get('temperature_min'), brightness_min=light_info.get('brightness_min'),
temperature_max=light_info.get('temperature_max'), brightness_max=light_info.get('brightness_max'),
hue_min=light_info.get('hue_min'), temperature_min=light_info.get('temperature_min'),
hue_max=light_info.get('hue_max'), temperature_max=light_info.get('temperature_max'),
saturation_min=light_info.get('saturation_min'), hue_min=light_info.get('hue_min'),
saturation_max=light_info.get('saturation_max'), hue_max=light_info.get('hue_max'),
brightness=( saturation_min=light_info.get('saturation_min'),
dev.get('state', {}) saturation_max=light_info.get('saturation_max'),
.get('color', {}) brightness=(
.get(light_info.get('brightness_name', 'brightness')) dev.get('state', {})
), .get('color', {})
temperature=( .get(light_info.get('brightness_name', 'brightness'))
dev.get('state', {}) ),
.get('color', {}) temperature=(
.get(light_info.get('temperature_name', 'temperature')) dev.get('state', {})
), .get('color', {})
hue=( .get(light_info.get('temperature_name', 'temperature'))
dev.get('state', {}) ),
.get('color', {}) hue=(
.get(light_info.get('hue_name', 'hue')) dev.get('state', {})
), .get('color', {})
saturation=( .get(light_info.get('hue_name', 'hue'))
dev.get('state', {}) ),
.get('color', {}) saturation=(
.get(light_info.get('saturation_name', 'saturation')) dev.get('state', {})
), .get('color', {})
x=( .get(light_info.get('saturation_name', 'saturation'))
dev.get('state', {}) ),
.get('color', {}) x=(
.get(light_info.get('x_name', 'x')) dev.get('state', {})
), .get('color', {})
y=( .get(light_info.get('x_name', 'x'))
dev.get('state', {}) ),
.get('color', {}) y=(
.get(light_info.get('y_name', 'y')) dev.get('state', {})
), .get('color', {})
description=dev_def.get('description'), .get(light_info.get('y_name', 'y'))
data=dev_info, ),
description=dev_def.get('description'),
data=dev_info,
)
) )
elif switch_info and dev.get('state', {}).get('state') is not None: elif switch_info and dev.get('state', {}).get('state') is not None:
converted_entity = Switch( converted_entities.append(
id=dev['ieee_address'], Switch(
name=dev.get('friendly_name'), id=dev['ieee_address'],
state=dev.get('state', {}).get('state') == switch_info['value_on'], name=dev.get('friendly_name'),
description=dev_def.get("description"), state=dev.get('state', {}).get('state')
data=dev_info, == switch_info['value_on'],
description=dev_def.get("description"),
data=dev_info,
)
) )
if converted_entity: if battery_info:
compatible_entities.append(converted_entity) converted_entities.append(
Battery(
id=dev['ieee_address'],
name=battery_info.get('friendly_name'),
value=dev.get('battery'),
description=battery_info.get('description'),
min=battery_info['min'],
max=battery_info['max'],
data=dev_info,
)
)
if converted_entities:
compatible_entities += converted_entities
return super().transform_entities(compatible_entities) # type: ignore return super().transform_entities(compatible_entities) # type: ignore
@ -1423,6 +1443,32 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
return {} return {}
@staticmethod
def _get_battery_meta(device_info: dict) -> dict:
exposes = (device_info.get('definition', {}) or {}).get('exposes', [])
for exposed in exposes:
for feature in exposed.get('features', []):
if (
feature.get('property') == 'battery'
and feature.get('type') == 'numeric'
):
return {
'friendly_name': (
device_info.get('friendly_name', '[Unnamed device]')
+ ' [Battery]'
),
'ieee_address': device_info.get('friendly_name'),
'property': feature['property'],
'description': feature.get('description'),
'value_min': feature.get('value_min', 0),
'value_max': feature.get('value_max', 100),
'unit': feature.get('unit', '%'),
'is_read_only': not bool(feature.get('access', 0) & 2),
'is_write_only': not bool(feature.get('access', 0) & 1),
}
return {}
@staticmethod @staticmethod
def _get_light_meta(device_info: dict) -> dict: def _get_light_meta(device_info: dict) -> dict:
exposes = (device_info.get('definition', {}) or {}).get('exposes', []) exposes = (device_info.get('definition', {}) or {}).get('exposes', [])