diff --git a/platypush/backend/http/webapp/src/components/panels/Entities/CurrentSensor.vue b/platypush/backend/http/webapp/src/components/panels/Entities/CurrentSensor.vue
new file mode 120000
index 0000000000..70b944608e
--- /dev/null
+++ b/platypush/backend/http/webapp/src/components/panels/Entities/CurrentSensor.vue
@@ -0,0 +1 @@
+Sensor.vue
\ No newline at end of file
diff --git a/platypush/backend/http/webapp/src/components/panels/Entities/EnergySensor.vue b/platypush/backend/http/webapp/src/components/panels/Entities/EnergySensor.vue
new file mode 120000
index 0000000000..70b944608e
--- /dev/null
+++ b/platypush/backend/http/webapp/src/components/panels/Entities/EnergySensor.vue
@@ -0,0 +1 @@
+Sensor.vue
\ No newline at end of file
diff --git a/platypush/backend/http/webapp/src/components/panels/Entities/HumiditySensor.vue b/platypush/backend/http/webapp/src/components/panels/Entities/HumiditySensor.vue
new file mode 120000
index 0000000000..70b944608e
--- /dev/null
+++ b/platypush/backend/http/webapp/src/components/panels/Entities/HumiditySensor.vue
@@ -0,0 +1 @@
+Sensor.vue
\ No newline at end of file
diff --git a/platypush/backend/http/webapp/src/components/panels/Entities/NumericSensor.vue b/platypush/backend/http/webapp/src/components/panels/Entities/NumericSensor.vue
new file mode 120000
index 0000000000..70b944608e
--- /dev/null
+++ b/platypush/backend/http/webapp/src/components/panels/Entities/NumericSensor.vue
@@ -0,0 +1 @@
+Sensor.vue
\ No newline at end of file
diff --git a/platypush/backend/http/webapp/src/components/panels/Entities/PowerSensor.vue b/platypush/backend/http/webapp/src/components/panels/Entities/PowerSensor.vue
new file mode 120000
index 0000000000..70b944608e
--- /dev/null
+++ b/platypush/backend/http/webapp/src/components/panels/Entities/PowerSensor.vue
@@ -0,0 +1 @@
+Sensor.vue
\ No newline at end of file
diff --git a/platypush/backend/http/webapp/src/components/panels/Entities/RawSensor.vue b/platypush/backend/http/webapp/src/components/panels/Entities/RawSensor.vue
new file mode 120000
index 0000000000..70b944608e
--- /dev/null
+++ b/platypush/backend/http/webapp/src/components/panels/Entities/RawSensor.vue
@@ -0,0 +1 @@
+Sensor.vue
\ No newline at end of file
diff --git a/platypush/backend/http/webapp/src/components/panels/Entities/Sensor.vue b/platypush/backend/http/webapp/src/components/panels/Entities/Sensor.vue
new file mode 100644
index 0000000000..9dda493ef7
--- /dev/null
+++ b/platypush/backend/http/webapp/src/components/panels/Entities/Sensor.vue
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
diff --git a/platypush/backend/http/webapp/src/components/panels/Entities/TemperatureSensor.vue b/platypush/backend/http/webapp/src/components/panels/Entities/TemperatureSensor.vue
new file mode 120000
index 0000000000..70b944608e
--- /dev/null
+++ b/platypush/backend/http/webapp/src/components/panels/Entities/TemperatureSensor.vue
@@ -0,0 +1 @@
+Sensor.vue
\ No newline at end of file
diff --git a/platypush/backend/http/webapp/src/components/panels/Entities/VoltageSensor.vue b/platypush/backend/http/webapp/src/components/panels/Entities/VoltageSensor.vue
new file mode 120000
index 0000000000..70b944608e
--- /dev/null
+++ b/platypush/backend/http/webapp/src/components/panels/Entities/VoltageSensor.vue
@@ -0,0 +1 @@
+Sensor.vue
\ No newline at end of file
diff --git a/platypush/backend/http/webapp/src/components/panels/Entities/meta.json b/platypush/backend/http/webapp/src/components/panels/Entities/meta.json
index 7e90c5670d..abdfd3667f 100644
--- a/platypush/backend/http/webapp/src/components/panels/Entities/meta.json
+++ b/platypush/backend/http/webapp/src/components/panels/Entities/meta.json
@@ -7,6 +7,14 @@
}
},
+ "current_sensor": {
+ "name": "Sensor",
+ "name_plural": "Sensors",
+ "icon": {
+ "class": "fas fa-bolt"
+ }
+ },
+
"device": {
"name": "Device",
"name_plural": "Devices",
@@ -23,6 +31,14 @@
}
},
+ "energy_sensor": {
+ "name": "Sensor",
+ "name_plural": "Sensors",
+ "icon": {
+ "class": "fas fa-plug"
+ }
+ },
+
"entity": {
"name": "Entity",
"name_plural": "Entities",
@@ -31,6 +47,14 @@
}
},
+ "humidity_sensor": {
+ "name": "Sensor",
+ "name_plural": "Sensors",
+ "icon": {
+ "class": "fas fa-droplet"
+ }
+ },
+
"light": {
"name": "Light",
"name_plural": "Lights",
@@ -43,7 +67,31 @@
"name": "Link Quality",
"name_plural": "Link Qualities",
"icon": {
- "class": "fas fa-signal"
+ "class": "fas fa-tower-broadcast"
+ }
+ },
+
+ "numeric_sensor": {
+ "name": "Sensor",
+ "name_plural": "Sensors",
+ "icon": {
+ "class": "fas fa-thermometer"
+ }
+ },
+
+ "power_sensor": {
+ "name": "Sensor",
+ "name_plural": "Sensors",
+ "icon": {
+ "class": "fas fa-plug"
+ }
+ },
+
+ "temperature_sensor": {
+ "name": "Sensor",
+ "name_plural": "Sensors",
+ "icon": {
+ "class": "fas fa-temperature-half"
}
},
@@ -53,5 +101,13 @@
"icon": {
"class": "fas fa-toggle-on"
}
+ },
+
+ "voltage_sensor": {
+ "name": "Sensor",
+ "name_plural": "Sensors",
+ "icon": {
+ "class": "fas fa-car-battery"
+ }
}
}
diff --git a/platypush/entities/electricity.py b/platypush/entities/electricity.py
new file mode 100644
index 0000000000..7c6a466cc8
--- /dev/null
+++ b/platypush/entities/electricity.py
@@ -0,0 +1,76 @@
+from sqlalchemy import Column, Integer, ForeignKey
+
+from .devices import entity_types_registry
+from .sensors import NumericSensor
+
+
+if not entity_types_registry.get('PowerSensor'):
+
+ class PowerSensor(NumericSensor):
+ __tablename__ = 'power_sensor'
+
+ id = Column(
+ Integer, ForeignKey(NumericSensor.id, ondelete='CASCADE'), primary_key=True
+ )
+
+ __mapper_args__ = {
+ 'polymorphic_identity': __tablename__,
+ }
+
+ entity_types_registry['PowerSensor'] = PowerSensor
+else:
+ PowerSensor = entity_types_registry['PowerSensor']
+
+
+if not entity_types_registry.get('CurrentSensor'):
+
+ class CurrentSensor(NumericSensor):
+ __tablename__ = 'current_sensor'
+
+ id = Column(
+ Integer, ForeignKey(NumericSensor.id, ondelete='CASCADE'), primary_key=True
+ )
+
+ __mapper_args__ = {
+ 'polymorphic_identity': __tablename__,
+ }
+
+ entity_types_registry['CurrentSensor'] = CurrentSensor
+else:
+ CurrentSensor = entity_types_registry['CurrentSensor']
+
+
+if not entity_types_registry.get('VoltageSensor'):
+
+ class VoltageSensor(NumericSensor):
+ __tablename__ = 'voltage_sensor'
+
+ id = Column(
+ Integer, ForeignKey(NumericSensor.id, ondelete='CASCADE'), primary_key=True
+ )
+
+ __mapper_args__ = {
+ 'polymorphic_identity': __tablename__,
+ }
+
+ entity_types_registry['VoltageSensor'] = VoltageSensor
+else:
+ VoltageSensor = entity_types_registry['VoltageSensor']
+
+
+if not entity_types_registry.get('EnergySensor'):
+
+ class EnergySensor(NumericSensor):
+ __tablename__ = 'energy_sensor'
+
+ id = Column(
+ Integer, ForeignKey(NumericSensor.id, ondelete='CASCADE'), primary_key=True
+ )
+
+ __mapper_args__ = {
+ 'polymorphic_identity': __tablename__,
+ }
+
+ entity_types_registry['EnergySensor'] = EnergySensor
+else:
+ EnergySensor = entity_types_registry['EnergySensor']
diff --git a/platypush/entities/humidity.py b/platypush/entities/humidity.py
new file mode 100644
index 0000000000..a78218ea17
--- /dev/null
+++ b/platypush/entities/humidity.py
@@ -0,0 +1,22 @@
+from sqlalchemy import Column, Integer, ForeignKey
+
+from .devices import entity_types_registry
+from .sensors import NumericSensor
+
+
+if not entity_types_registry.get('HumiditySensor'):
+
+ class HumiditySensor(NumericSensor):
+ __tablename__ = 'humidity_sensor'
+
+ id = Column(
+ Integer, ForeignKey(NumericSensor.id, ondelete='CASCADE'), primary_key=True
+ )
+
+ __mapper_args__ = {
+ 'polymorphic_identity': __tablename__,
+ }
+
+ entity_types_registry['HumiditySensor'] = HumiditySensor
+else:
+ HumiditySensor = entity_types_registry['HumiditySensor']
diff --git a/platypush/entities/sensors.py b/platypush/entities/sensors.py
index abc998d9cc..afd2d46378 100644
--- a/platypush/entities/sensors.py
+++ b/platypush/entities/sensors.py
@@ -3,9 +3,13 @@ from sqlalchemy import Column, Integer, ForeignKey, Numeric, String
from .devices import Device, entity_types_registry
+class Sensor(Device):
+ __abstract__ = True
+
+
if not entity_types_registry.get('RawSensor'):
- class RawSensor(Device):
+ class RawSensor(Sensor):
__tablename__ = 'raw_sensor'
id = Column(
@@ -24,7 +28,7 @@ else:
if not entity_types_registry.get('NumericSensor'):
- class NumericSensor(Device):
+ class NumericSensor(Sensor):
__tablename__ = 'numeric_sensor'
id = Column(
diff --git a/platypush/entities/temperature.py b/platypush/entities/temperature.py
new file mode 100644
index 0000000000..e9b2d12abd
--- /dev/null
+++ b/platypush/entities/temperature.py
@@ -0,0 +1,22 @@
+from sqlalchemy import Column, Integer, ForeignKey
+
+from .devices import entity_types_registry
+from .sensors import NumericSensor
+
+
+if not entity_types_registry.get('TemperatureSensor'):
+
+ class TemperatureSensor(NumericSensor):
+ __tablename__ = 'temperature_sensor'
+
+ id = Column(
+ Integer, ForeignKey(NumericSensor.id, ondelete='CASCADE'), primary_key=True
+ )
+
+ __mapper_args__ = {
+ 'polymorphic_identity': __tablename__,
+ }
+
+ entity_types_registry['TemperatureSensor'] = TemperatureSensor
+else:
+ TemperatureSensor = entity_types_registry['TemperatureSensor']
diff --git a/platypush/plugins/zigbee/mqtt/__init__.py b/platypush/plugins/zigbee/mqtt/__init__.py
index 04b3af1837..3988ec23fe 100644
--- a/platypush/plugins/zigbee/mqtt/__init__.py
+++ b/platypush/plugins/zigbee/mqtt/__init__.py
@@ -6,15 +6,24 @@ from typing import Optional, List, Any, Dict, Union
from platypush.entities import manages
from platypush.entities.batteries import Battery
+from platypush.entities.electricity import (
+ CurrentSensor,
+ EnergySensor,
+ PowerSensor,
+ VoltageSensor,
+)
+from platypush.entities.humidity import HumiditySensor
from platypush.entities.lights import Light
from platypush.entities.linkquality import LinkQuality
+from platypush.entities.sensors import Sensor, NumericSensor
from platypush.entities.switches import Switch
+from platypush.entities.temperature import TemperatureSensor
from platypush.message import Mapping
from platypush.message.response import Response
from platypush.plugins.mqtt import MqttPlugin, action
-@manages(Light, Switch, LinkQuality, Battery)
+@manages(Light, Switch, LinkQuality, Battery, Sensor)
class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
"""
This plugin allows you to interact with Zigbee devices over MQTT through any Zigbee sniffer and
@@ -170,7 +179,6 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
if not dev:
continue
- converted_entities = []
dev_def = dev.get("definition") or {}
dev_info = {
"type": dev.get("type"),
@@ -187,13 +195,12 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
light_info = self._get_light_meta(dev)
switch_info = self._get_switch_meta(dev)
- battery_info = self._get_battery_meta(dev)
- link_quality_info = self._get_link_quality_meta(dev)
+ sensors = self._get_sensors(dev)
if light_info:
- converted_entities.append(
+ compatible_entities.append(
Light(
- id=dev['ieee_address'],
+ id=f'{dev["ieee_address"]}|light',
name=dev.get('friendly_name'),
on=dev.get('state', {}).get('state')
== switch_info.get('value_on'),
@@ -240,52 +247,21 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
)
)
elif switch_info and dev.get('state', {}).get('state') is not None:
- converted_entities.append(
+ compatible_entities.append(
Switch(
- id=dev['ieee_address'],
+ id=f'{dev["ieee_address"]}:switch',
name=dev.get('friendly_name'),
state=dev.get('state', {}).get('state')
== switch_info['value_on'],
description=dev_def.get("description"),
data=dev_info,
- is_read_only=link_quality_info['is_read_only'],
- is_write_only=link_quality_info['is_write_only'],
+ is_read_only=switch_info['is_read_only'],
+ is_write_only=switch_info['is_write_only'],
)
)
- if battery_info:
- converted_entities.append(
- Battery(
- id=dev['ieee_address'],
- name=battery_info.get('friendly_name'),
- value=dev.get('state', {}).get('battery'),
- description=battery_info.get('description'),
- min=battery_info['min'],
- max=battery_info['max'],
- is_read_only=battery_info['is_read_only'],
- is_write_only=battery_info['is_write_only'],
- data=dev_info,
- )
- )
-
- if link_quality_info:
- converted_entities.append(
- LinkQuality(
- id=dev['ieee_address'],
- name=link_quality_info.get('friendly_name'),
- value=dev.get('state', {}).get('linkquality'),
- description=link_quality_info.get('description'),
- min=link_quality_info['min'],
- max=link_quality_info['max'],
- unit=link_quality_info['unit'],
- is_read_only=link_quality_info['is_read_only'],
- is_write_only=link_quality_info['is_write_only'],
- data=dev_info,
- )
- )
-
- if converted_entities:
- compatible_entities += converted_entities
+ if sensors:
+ compatible_entities += sensors
return super().transform_entities(compatible_entities) # type: ignore
@@ -619,7 +595,7 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
"""
Change the options of a device. Options can only be changed, not added or deleted.
- :param device: Display name of the device.
+ :param device: Display name or IEEE address of the device.
:param option: Option name.
:param value: New value.
:param kwargs: Extra arguments to be passed to :meth:`platypush.plugins.mqtt.MqttPlugin.publish``
@@ -767,7 +743,6 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
device, self._info['devices_by_addr'].get(device, {})
)
- # noinspection PyShadowingBuiltins
@action
def device_get(
self, device: str, property: Optional[str] = None, **kwargs
@@ -786,7 +761,7 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
kwargs = self._mqtt_args(**kwargs)
device_info = self._get_device_info(device)
if device_info:
- device = device_info.get('friendly_name') or device_info['ieee_address']
+ device = device_info.get('friendly_name') or self._ieee_address(device_info)
if property:
properties = self.publish(
@@ -904,7 +879,6 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
"""
return self.devices_get([device] if device else None, *args, **kwargs)
- # noinspection PyShadowingBuiltins,DuplicatedCode
@action
def device_set(
self,
@@ -1381,7 +1355,7 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
"""
switch_info = self._get_switch_info(device)
assert switch_info, '{} is not a valid switch'.format(device)
- device = switch_info.get('friendly_name') or switch_info['ieee_address']
+ device = switch_info.get('friendly_name') or self._ieee_address(switch_info)
props = self.device_set(
device, switch_info['property'], switch_info['value_on']
).output # type: ignore[reportGeneralTypeIssues]
@@ -1397,7 +1371,7 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
"""
switch_info = self._get_switch_info(device)
assert switch_info, '{} is not a valid switch'.format(device)
- device = switch_info.get('friendly_name') or switch_info['ieee_address']
+ device = switch_info.get('friendly_name') or self._ieee_address(switch_info)
props = self.device_set(
device, switch_info['property'], switch_info['value_off']
).output # type: ignore[reportGeneralTypeIssues]
@@ -1408,12 +1382,12 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
@action
def toggle(self, device, *_, **__) -> dict:
"""
- Implements :meth:`platypush.plugins.switch.plugin.SwitchPlugin.toggle` and toggles a Zigbee device with a
- writable binary property.
+ Implements :meth:`platypush.plugins.switch.plugin.SwitchPlugin.toggle`
+ and toggles a Zigbee device with a writable binary property.
"""
switch_info = self._get_switch_info(device)
assert switch_info, '{} is not a valid switch'.format(device)
- device = switch_info.get('friendly_name') or switch_info['ieee_address']
+ device = switch_info.get('friendly_name') or self._ieee_address(switch_info)
props = self.device_set(
device, switch_info['property'], switch_info['value_toggle']
).output # type: ignore[reportGeneralTypeIssues]
@@ -1442,7 +1416,28 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
}
@staticmethod
- def _get_switch_meta(device_info: dict) -> dict:
+ def _is_read_only(feature: dict) -> bool:
+ return bool(feature.get('access', 0) & 2) == 0 and (
+ bool(feature.get('access', 0) & 1) == 1
+ or bool(feature.get('access', 0) & 4) == 1
+ )
+
+ @staticmethod
+ def _is_write_only(feature: dict) -> bool:
+ return bool(feature.get('access', 0) & 2) == 1 and (
+ bool(feature.get('access', 0) & 1) == 0
+ or bool(feature.get('access', 0) & 4) == 0
+ )
+
+ @staticmethod
+ def _ieee_address(device: dict) -> str:
+ # Entity value IDs are stored in the `
:`
+ # format. Therefore, we need to split by `:` if we want to
+ # retrieve the original address.
+ return device['ieee_address'].split(':')[0]
+
+ @classmethod
+ def _get_switch_meta(cls, device_info: dict) -> dict:
exposes = (device_info.get('definition', {}) or {}).get('exposes', [])
for exposed in exposes:
for feature in exposed.get('features', []):
@@ -1459,69 +1454,67 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
'value_on': feature['value_on'],
'value_off': feature['value_off'],
'value_toggle': feature.get('value_toggle', None),
- 'is_read_only': not bool(feature.get('access', 0) & 2),
- 'is_write_only': not bool(feature.get('access', 0) & 1),
+ 'is_read_only': cls._is_read_only(feature),
+ 'is_write_only': cls._is_write_only(feature),
}
return {}
- @staticmethod
- def _get_battery_meta(device_info: dict) -> dict:
- exposes = (device_info.get('definition', {}) or {}).get('exposes', [])
+ @classmethod
+ def _get_sensors(cls, device_info: dict) -> List[Sensor]:
+ sensors = []
+ exposes = [
+ exposed
+ for exposed in (device_info.get('definition', {}) or {}).get('exposes', [])
+ if (exposed.get('property') and cls._is_read_only(exposed))
+ ]
+
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]')
- + ' ['
- + feature.get('description', 'Battery')
- + ']'
- ),
- 'ieee_address': device_info.get('friendly_name'),
- 'property': feature['property'],
- 'description': feature.get('description'),
- 'min': feature.get('value_min', 0),
- '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),
- }
+ entity_type = None
+ sensor_args = {
+ 'id': f'{device_info["ieee_address"]}:{exposed["property"]}',
+ 'name': (
+ device_info.get('friendly_name', '[Unnamed device]')
+ + ' ['
+ + exposed.get('description', '')
+ + ']'
+ ),
+ 'value': device_info.get('state', {}).get(exposed['property']),
+ 'description': exposed.get('description'),
+ 'min': exposed.get('value_min'),
+ 'max': exposed.get('value_max'),
+ 'unit': exposed.get('unit'),
+ 'is_read_only': cls._is_read_only(exposed),
+ 'is_write_only': cls._is_read_only(exposed),
+ 'data': device_info,
+ }
- return {}
+ if exposed.get('property') == 'battery':
+ entity_type = Battery
+ elif exposed.get('property') == 'linkquality':
+ entity_type = LinkQuality
+ elif exposed.get('property') == 'current':
+ entity_type = CurrentSensor
+ elif exposed.get('property') == 'energy':
+ entity_type = EnergySensor
+ elif exposed.get('property') == 'power':
+ entity_type = PowerSensor
+ elif exposed.get('property') == 'voltage':
+ entity_type = VoltageSensor
+ elif exposed.get('property', '').endswith('temperature'):
+ entity_type = TemperatureSensor
+ elif exposed.get('property', '').endswith('humidity'):
+ entity_type = HumiditySensor
+ elif exposed.get('type') == 'numeric':
+ entity_type = NumericSensor
- @staticmethod
- def _get_link_quality_meta(device_info: dict) -> dict:
- exposes = (device_info.get('definition', {}) or {}).get('exposes', [])
- for exposed in exposes:
- if (
- exposed.get('property') == 'linkquality'
- and exposed.get('type') == 'numeric'
- ):
- return {
- 'friendly_name': (
- device_info.get('friendly_name', '[Unnamed device]')
- + ' ['
- + exposed.get('description', 'Link Quality')
- + ']'
- ),
- 'ieee_address': device_info.get('friendly_name'),
- 'property': exposed['property'],
- 'description': exposed.get('description'),
- 'min': exposed.get('value_min', 0),
- 'max': exposed.get('value_max', 100),
- 'unit': exposed.get('unit', '%'),
- 'is_read_only': not bool(exposed.get('access', 0) & 2),
- 'is_write_only': not bool(exposed.get('access', 0) & 1),
- }
+ if entity_type:
+ sensors.append(entity_type(**sensor_args))
- return {}
+ return sensors
- @staticmethod
- def _get_light_meta(device_info: dict) -> dict:
+ @classmethod
+ def _get_light_meta(cls, device_info: dict) -> dict:
exposes = (device_info.get('definition', {}) or {}).get('exposes', [])
for exposed in exposes:
if exposed.get('type') == 'light':
@@ -1543,8 +1536,8 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
'value_off': feature['value_off'],
'state_name': feature['name'],
'value_toggle': feature.get('value_toggle', None),
- 'is_read_only': not bool(feature.get('access', 0) & 2),
- 'is_write_only': not bool(feature.get('access', 0) & 1),
+ 'is_read_only': cls._is_read_only(feature),
+ 'is_write_only': cls._is_write_only(feature),
}
elif (
feature.get('property') == 'brightness'
@@ -1556,8 +1549,8 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
'brightness_name': feature['name'],
'brightness_min': feature['value_min'],
'brightness_max': feature['value_max'],
- 'is_read_only': not bool(feature.get('access', 0) & 2),
- 'is_write_only': not bool(feature.get('access', 0) & 1),
+ 'is_read_only': cls._is_read_only(feature),
+ 'is_write_only': cls._is_write_only(feature),
}
elif (
feature.get('property') == 'color_temp'
@@ -1569,8 +1562,8 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
'temperature_name': feature['name'],
'temperature_min': feature['value_min'],
'temperature_max': feature['value_max'],
- 'is_read_only': not bool(feature.get('access', 0) & 2),
- 'is_write_only': not bool(feature.get('access', 0) & 1),
+ 'is_read_only': cls._is_read_only(feature),
+ 'is_write_only': cls._is_write_only(feature),
}
elif (
feature.get('property') == 'color'
@@ -1586,12 +1579,8 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
'hue_max': color_feature.get(
'value_max', 65535
),
- 'is_read_only': not bool(
- feature.get('access', 0) & 2
- ),
- 'is_write_only': not bool(
- feature.get('access', 0) & 1
- ),
+ 'is_read_only': cls._is_read_only(feature),
+ 'is_write_only': cls._is_write_only(feature),
}
)
elif color_feature.get('property') == 'saturation':
@@ -1604,12 +1593,8 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
'saturation_max': color_feature.get(
'value_max', 255
),
- 'is_read_only': not bool(
- feature.get('access', 0) & 2
- ),
- 'is_write_only': not bool(
- feature.get('access', 0) & 1
- ),
+ 'is_read_only': cls._is_read_only(feature),
+ 'is_write_only': cls._is_write_only(feature),
}
)
elif color_feature.get('property') == 'x':
@@ -1618,12 +1603,8 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
'x_name': color_feature['name'],
'x_min': color_feature.get('value_min', 0.0),
'x_max': color_feature.get('value_max', 1.0),
- 'is_read_only': not bool(
- feature.get('access', 0) & 2
- ),
- 'is_write_only': not bool(
- feature.get('access', 0) & 1
- ),
+ 'is_read_only': cls._is_read_only(feature),
+ 'is_write_only': cls._is_write_only(feature),
}
)
elif color_feature.get('property') == 'y':
@@ -1632,12 +1613,8 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
'y_name': color_feature['name'],
'y_min': color_feature.get('value_min', 0),
'y_max': color_feature.get('value_max', 255),
- 'is_read_only': not bool(
- feature.get('access', 0) & 2
- ),
- 'is_write_only': not bool(
- feature.get('access', 0) & 1
- ),
+ 'is_read_only': cls._is_read_only(feature),
+ 'is_write_only': cls._is_write_only(feature),
}
)
@@ -1662,7 +1639,7 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
continue
switches_info[
- device.get('friendly_name', device.get('ieee_address'))
+ device.get('friendly_name', device['ieee_address'] + ':switch')
] = info
return switches_info
@@ -1675,7 +1652,6 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
``state`` property that can be set to ``ON`` or ``OFF``).
"""
switches_info = self._get_switches_info()
- # noinspection PyUnresolvedReferences
return [
self._properties_to_switch(
device=name, props=switch, switch_info=switches_info[name]
@@ -1694,7 +1670,7 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
devices = [
dev
for dev in self._get_network_info().get('devices', [])
- if dev.get('ieee_address') in lights or dev.get('friendly_name') in lights
+ if self._ieee_address(dev) in lights or dev.get('friendly_name') in lights
]
for dev in devices: