Added support for EnumSensor entities

This commit is contained in:
Fabio Manganiello 2022-11-21 00:04:07 +01:00
parent d171000a0e
commit b9e6614b04
Signed by: blacklight
GPG key ID: D90FBA7F76362774
6 changed files with 162 additions and 40 deletions

View file

@ -0,0 +1,60 @@
<template>
<div class="entity sensor-container">
<div class="head">
<div class="col-1 icon">
<EntityIcon
:icon="value.meta?.icon || {}"
:loading="loading"
:error="error" />
</div>
<div class="col-s-8 col-m-9 label">
<div class="name" v-text="value.name" />
</div>
<div class="col-s-3 col-m-2 pull-right"
v-if="value.value != null">
<span class="unit" v-text="value.unit"
v-if="value.unit != null" />
<span class="value" v-text="displayValue(value.value)" />
</div>
</div>
</div>
</template>
<script>
import EntityIcon from "./EntityIcon"
import Sensor from "./Sensor"
export default {
name: 'EnumSensor',
components: {EntityIcon},
mixins: [Sensor],
methods: {
displayValue(val) {
if (this.value?.values && typeof(this.value.values) === 'object')
return this.value.values[val] || val
return val
},
},
}
</script>
<style lang="scss" scoped>
@import "common";
.sensor-container {
.head {
.value {
font-size: 1.1em;
font-weight: bold;
opacity: 0.7;
}
.unit {
margin-left: 0.2em;
}
}
}
</style>

View file

@ -127,6 +127,14 @@
} }
}, },
"enum_sensor": {
"name": "Sensor",
"name_plural": "Sensors",
"icon": {
"class": "fas fa-thermometer"
}
},
"sensor": { "sensor": {
"name": "Sensor", "name": "Sensor",
"name_plural": "Sensors", "name_plural": "Sensors",

View file

@ -106,7 +106,7 @@ class ZwaveMqttBackend(MqttBackend):
value: Optional[dict] = None, value: Optional[dict] = None,
**kwargs, **kwargs,
): ):
if value and 'id' not in value: if node and value and 'id' not in value:
value_id = f"{value['commandClass']}-{value.get('endpoint', 0)}-{value['property']}" value_id = f"{value['commandClass']}-{value.get('endpoint', 0)}-{value['property']}"
if 'propertyKey' in value: if 'propertyKey' in value:
value_id += '-' + str(value['propertyKey']) value_id += '-' + str(value['propertyKey'])

View file

@ -1,6 +1,14 @@
import logging import logging
from sqlalchemy import Column, Integer, ForeignKey, Boolean, Numeric, String from sqlalchemy import (
Boolean,
Column,
ForeignKey,
Integer,
JSON,
Numeric,
String,
)
from .devices import Device, entity_types_registry from .devices import Device, entity_types_registry
@ -83,3 +91,23 @@ if not entity_types_registry.get('BinarySensor'):
entity_types_registry['BinarySensor'] = BinarySensor entity_types_registry['BinarySensor'] = BinarySensor
else: else:
BinarySensor = entity_types_registry['BinarySensor'] BinarySensor = entity_types_registry['BinarySensor']
if not entity_types_registry.get('EnumSensor'):
class EnumSensor(Sensor):
__tablename__ = 'enum_sensor'
id = Column(
Integer, ForeignKey(Device.id, ondelete='CASCADE'), primary_key=True
)
value = Column(String)
values = Column(JSON)
__mapper_args__ = {
'polymorphic_identity': __tablename__,
}
entity_types_registry['EnumSensor'] = EnumSensor
else:
EnumSensor = entity_types_registry['EnumSensor']

View file

@ -17,7 +17,12 @@ from platypush.entities.electricity import (
from platypush.entities.humidity import HumiditySensor from platypush.entities.humidity import HumiditySensor
from platypush.entities.lights import Light from platypush.entities.lights import Light
from platypush.entities.linkquality import LinkQuality from platypush.entities.linkquality import LinkQuality
from platypush.entities.sensors import Sensor, BinarySensor, NumericSensor from platypush.entities.sensors import (
BinarySensor,
EnumSensor,
NumericSensor,
Sensor,
)
from platypush.entities.switches import Switch, EnumSwitch from platypush.entities.switches import Switch, EnumSwitch
from platypush.entities.temperature import TemperatureSensor from platypush.entities.temperature import TemperatureSensor
from platypush.message import Mapping from platypush.message import Mapping
@ -1586,6 +1591,9 @@ class ZigbeeMqttPlugin(MqttPlugin): # lgtm [py/missing-call-to-init]
sensor_args['value'] = sensor_args['value'] == exposed.get( sensor_args['value'] = sensor_args['value'] == exposed.get(
'value_on', True 'value_on', True
) )
elif exposed.get('type') == 'enum':
entity_type = EnumSensor
sensor_args['values'] = exposed.get('values', [])
elif exposed.get('type') == 'numeric': elif exposed.get('type') == 'numeric':
entity_type = NumericSensor entity_type = NumericSensor

View file

@ -26,7 +26,7 @@ from platypush.entities.electricity import (
VoltageSensor, VoltageSensor,
) )
from platypush.entities.humidity import HumiditySensor from platypush.entities.humidity import HumiditySensor
from platypush.entities.sensors import BinarySensor, NumericSensor from platypush.entities.sensors import BinarySensor, EnumSensor, NumericSensor
from platypush.entities.switches import Switch from platypush.entities.switches import Switch
from platypush.entities.temperature import TemperatureSensor from platypush.entities.temperature import TemperatureSensor
from platypush.message.event.zwave import ZwaveNodeRenamedEvent, ZwaveNodeEvent from platypush.message.event.zwave import ZwaveNodeRenamedEvent, ZwaveNodeEvent
@ -507,46 +507,64 @@ class ZwaveMqttPlugin(MqttPlugin, ZwaveBasePlugin):
def _get_sensor_args( def _get_sensor_args(
cls, value: Mapping cls, value: Mapping
) -> Tuple[Optional[Type], Optional[Mapping]]: ) -> Tuple[Optional[Type], Optional[Mapping]]:
if not value.get('is_read_only'): sensor_type, args = None, None
return None, None known_sensor_classes = {
'battery',
'door_lock',
'lock',
'meter',
'notification',
'sensor_alarm',
'sensor_binary',
'sensor_multilevel',
'thermostat_fan_mode',
'thermostat_fan_state',
'thermostat_heating',
}
if ( if value.get('is_read_only') and cls._matches_classes(
cls._matches_classes(value, 'sensor_binary', 'sensor_alarm', 'meter') value, *known_sensor_classes
and value.get('type') == 'Bool'
): ):
return ( if value.get('type') == 'Bool':
BinarySensor, sensor_type, args = (
{ BinarySensor,
'value': value.get('data', False), {
}, 'value': value.get('data', False),
) },
)
elif value.get('type') == 'List':
sensor_type, args = (
EnumSensor,
{
'value': value.get('data'),
'values': {
i['value']: i['text'] for i in value.get('data_items', [])
},
},
)
elif value.get('type') == 'Decimal':
sensor_type = NumericSensor
if re.search(r'\s*power$', value['property_id'], re.IGNORECASE):
sensor_type = PowerSensor
if re.search(r'\s*voltage$', value['property_id'], re.IGNORECASE):
sensor_type = VoltageSensor
elif re.search(
r'\s*consumption$', value['property_id'], re.IGNORECASE
) or re.search(r'Wh$', (value.get('units') or '')):
sensor_type = EnergySensor
elif re.search(r'\s*temperature$', value['property_id'], re.IGNORECASE):
sensor_type = TemperatureSensor
elif re.search(r'\s*humidity$', value['property_id'], re.IGNORECASE):
sensor_type = HumiditySensor
if ( args = {
cls._matches_classes(value, 'sensor_multilevel', 'sensor_alarm', 'meter') 'value': value.get('data'),
and value.get('type') == 'Decimal' 'min': value.get('min'),
): 'max': value.get('max'),
args = { 'unit': value.get('units'),
'value': value.get('data'), }
'min': value.get('min'),
'max': value.get('max'),
'unit': value.get('units'),
}
sensor_type = NumericSensor return sensor_type, args
if re.search(r'\s*power$', value['property_id'], re.IGNORECASE):
sensor_type = PowerSensor
if re.search(r'\s*voltage$', value['property_id'], re.IGNORECASE):
sensor_type = VoltageSensor
elif re.search(r'Wh$', value.get('units', '')):
sensor_type = EnergySensor
elif re.search(r'\s*temperature$', value['property_id'], re.IGNORECASE):
sensor_type = TemperatureSensor
elif re.search(r'\s*humidity$', value['property_id'], re.IGNORECASE):
sensor_type = HumiditySensor
return sensor_type, args
return None, None
@classmethod @classmethod
def _is_battery(cls, value: Mapping): def _is_battery(cls, value: Mapping):