diff --git a/platypush/backend/http/webapp/src/components/panels/Entities/BinarySensor.vue b/platypush/backend/http/webapp/src/components/panels/Entities/BinarySensor.vue new file mode 100644 index 00000000..19625332 --- /dev/null +++ b/platypush/backend/http/webapp/src/components/panels/Entities/BinarySensor.vue @@ -0,0 +1,50 @@ + + + + + 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 abdfd366..4fba8844 100644 --- a/platypush/backend/http/webapp/src/components/panels/Entities/meta.json +++ b/platypush/backend/http/webapp/src/components/panels/Entities/meta.json @@ -71,14 +71,6 @@ } }, - "numeric_sensor": { - "name": "Sensor", - "name_plural": "Sensors", - "icon": { - "class": "fas fa-thermometer" - } - }, - "power_sensor": { "name": "Sensor", "name_plural": "Sensors", @@ -109,5 +101,29 @@ "icon": { "class": "fas fa-car-battery" } + }, + + "binary_sensor": { + "name": "Sensor", + "name_plural": "Sensors", + "icon": { + "class": "fas fa-thermometer" + } + }, + + "numeric_sensor": { + "name": "Sensor", + "name_plural": "Sensors", + "icon": { + "class": "fas fa-thermometer" + } + }, + + "sensor": { + "name": "Sensor", + "name_plural": "Sensors", + "icon": { + "class": "fas fa-thermometer" + } } } diff --git a/platypush/entities/sensors.py b/platypush/entities/sensors.py index afd2d463..efcf3e57 100644 --- a/platypush/entities/sensors.py +++ b/platypush/entities/sensors.py @@ -1,7 +1,11 @@ -from sqlalchemy import Column, Integer, ForeignKey, Numeric, String +import logging + +from sqlalchemy import Column, Integer, ForeignKey, Boolean, Numeric, String from .devices import Device, entity_types_registry +logger = logging.getLogger(__name__) + class Sensor(Device): __abstract__ = True @@ -46,3 +50,36 @@ if not entity_types_registry.get('NumericSensor'): entity_types_registry['NumericSensor'] = NumericSensor else: NumericSensor = entity_types_registry['NumericSensor'] + + +if not entity_types_registry.get('BinarySensor'): + + class BinarySensor(Sensor): + __tablename__ = 'binary_sensor' + + def __init__(self, *args, value=None, **kwargs): + if isinstance(value, str): + value = value.lower() + + if value in {True, 1, '1', 't', 'true', 'on'}: + value = True + elif value in {False, 0, '0', 'f', 'false', 'off'}: + value = False + elif value is not None: + logger.warning(f'Unsupported value for BinarySensor type: {value}') + value = None + + super().__init__(*args, value=value, **kwargs) + + id = Column( + Integer, ForeignKey(Device.id, ondelete='CASCADE'), primary_key=True + ) + value = Column(Boolean) + + __mapper_args__ = { + 'polymorphic_identity': __tablename__, + } + + entity_types_registry['BinarySensor'] = BinarySensor +else: + BinarySensor = entity_types_registry['BinarySensor'] diff --git a/platypush/plugins/zigbee/mqtt/__init__.py b/platypush/plugins/zigbee/mqtt/__init__.py index 2271cedd..9fe0970f 100644 --- a/platypush/plugins/zigbee/mqtt/__init__.py +++ b/platypush/plugins/zigbee/mqtt/__init__.py @@ -16,7 +16,7 @@ from platypush.entities.electricity import ( 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.sensors import Sensor, BinarySensor, NumericSensor from platypush.entities.switches import Switch from platypush.entities.temperature import TemperatureSensor from platypush.message import Mapping @@ -1495,14 +1495,20 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init] ), '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), + 'is_write_only': cls._is_write_only(exposed), 'data': device_info, } + if exposed.get('type') == 'numeric': + sensor_args.update( + { + 'min': exposed.get('value_min'), + 'max': exposed.get('value_max'), + 'unit': exposed.get('unit'), + } + ) + if exposed.get('property') == 'battery': entity_type = Battery elif exposed.get('property') == 'linkquality': @@ -1519,6 +1525,11 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init] entity_type = TemperatureSensor elif exposed.get('property', '').endswith('humidity'): entity_type = HumiditySensor + elif exposed.get('type') == 'binary': + entity_type = BinarySensor + sensor_args['value'] = sensor_args['value'] == exposed.get( + 'value_on', True + ) elif exposed.get('type') == 'numeric': entity_type = NumericSensor