forked from platypush/platypush
Support for battery entities
This commit is contained in:
parent
cdacf50fc7
commit
d61b053f72
6 changed files with 240 additions and 13 deletions
|
@ -0,0 +1,123 @@
|
||||||
|
<template>
|
||||||
|
<div class="entity battery-container">
|
||||||
|
<div class="head">
|
||||||
|
<div class="col-1 icon">
|
||||||
|
<EntityIcon
|
||||||
|
:icon="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 buttons pull-right">
|
||||||
|
<span class="value-percent"
|
||||||
|
v-text="valuePercent + '%'"
|
||||||
|
v-if="valuePercent != null" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import EntityMixin from "./EntityMixin"
|
||||||
|
import EntityIcon from "./EntityIcon"
|
||||||
|
|
||||||
|
const thresholds = [
|
||||||
|
{
|
||||||
|
iconClass: 'full',
|
||||||
|
color: '#157145',
|
||||||
|
value: 0.9,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
iconClass: 'three-quarters',
|
||||||
|
color: '#94C595',
|
||||||
|
value: 0.825,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
iconClass: 'half',
|
||||||
|
color: '#F0B67F',
|
||||||
|
value: 0.625,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
iconClass: 'quarter',
|
||||||
|
color: '#FE5F55',
|
||||||
|
value: 0.375,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
iconClass: 'low',
|
||||||
|
color: '#CC444B',
|
||||||
|
value: 0.15,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
iconClass: 'empty',
|
||||||
|
color: '#EC0B43',
|
||||||
|
value: 0.05,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Battery',
|
||||||
|
components: {EntityIcon},
|
||||||
|
mixins: [EntityMixin],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
expanded: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
valuePercent() {
|
||||||
|
if (this.value?.value == null)
|
||||||
|
return null
|
||||||
|
|
||||||
|
const min = this.value.min || 0
|
||||||
|
const max = this.value.max || 100
|
||||||
|
return ((100 * this.value.value) / (max - min)).toFixed(0)
|
||||||
|
},
|
||||||
|
|
||||||
|
icon() {
|
||||||
|
const icon = {...(this.value.meta?.icon || {})}
|
||||||
|
let value = this.valuePercent
|
||||||
|
let threshold = thresholds[0]
|
||||||
|
|
||||||
|
if (value != null) {
|
||||||
|
value = parseFloat(value) / 100
|
||||||
|
for (const t of thresholds) {
|
||||||
|
if (value > t.value)
|
||||||
|
break
|
||||||
|
threshold = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
icon['class'] = `fas fa-battery-${threshold.iconClass}`
|
||||||
|
icon['color'] = threshold.color
|
||||||
|
return icon
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
prevent(event) {
|
||||||
|
event.stopPropagation()
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "common";
|
||||||
|
|
||||||
|
.battery-container {
|
||||||
|
.head {
|
||||||
|
.value-percent {
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bold;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"entity": {
|
"battery": {
|
||||||
"name": "Entity",
|
"name": "Battery",
|
||||||
"name_plural": "Entities",
|
"name_plural": "Batteries",
|
||||||
"icon": {
|
"icon": {
|
||||||
"class": "fas fa-circle-question"
|
"class": "fas fa-battery-full"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -15,11 +15,19 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"switch": {
|
"dimmer": {
|
||||||
"name": "Switch",
|
"name": "Dimmer",
|
||||||
"name_plural": "Switches",
|
"name_plural": "Dimmers",
|
||||||
"icon": {
|
"icon": {
|
||||||
"class": "fas fa-toggle-on"
|
"class": "fas fa-gauge"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"entity": {
|
||||||
|
"name": "Entity",
|
||||||
|
"name_plural": "Entities",
|
||||||
|
"icon": {
|
||||||
|
"class": "fas fa-circle-question"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -31,11 +39,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"dimmer": {
|
"switch": {
|
||||||
"name": "Dimmer",
|
"name": "Switch",
|
||||||
"name_plural": "Dimmers",
|
"name_plural": "Switches",
|
||||||
"icon": {
|
"icon": {
|
||||||
"class": "fas fa-gauge"
|
"class": "fas fa-toggle-on"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
37
platypush/entities/batteries.py
Normal file
37
platypush/entities/batteries.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
from sqlalchemy import Column, Integer, ForeignKey
|
||||||
|
|
||||||
|
from .devices import entity_types_registry
|
||||||
|
from .sensors import NumericSensor
|
||||||
|
|
||||||
|
|
||||||
|
if not entity_types_registry.get('Battery'):
|
||||||
|
|
||||||
|
class Battery(NumericSensor):
|
||||||
|
__tablename__ = 'battery'
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*args,
|
||||||
|
value,
|
||||||
|
unit: str = '%',
|
||||||
|
min: float = 0,
|
||||||
|
max: float = 100,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.value = float(value)
|
||||||
|
self.unit = unit
|
||||||
|
self.min = min
|
||||||
|
self.max = max
|
||||||
|
|
||||||
|
id = Column(
|
||||||
|
Integer, ForeignKey(NumericSensor.id, ondelete='CASCADE'), primary_key=True
|
||||||
|
)
|
||||||
|
|
||||||
|
__mapper_args__ = {
|
||||||
|
'polymorphic_identity': __tablename__,
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_types_registry['Battery'] = Battery
|
||||||
|
else:
|
||||||
|
Battery = entity_types_registry['Battery']
|
43
platypush/entities/sensors.py
Normal file
43
platypush/entities/sensors.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
from sqlalchemy import Column, Integer, ForeignKey, Numeric, String
|
||||||
|
|
||||||
|
from .devices import Device, entity_types_registry
|
||||||
|
|
||||||
|
|
||||||
|
if not entity_types_registry.get('RawSensor'):
|
||||||
|
|
||||||
|
class RawSensor(Device):
|
||||||
|
__tablename__ = 'raw_sensor'
|
||||||
|
|
||||||
|
id = Column(
|
||||||
|
Integer, ForeignKey(Device.id, ondelete='CASCADE'), primary_key=True
|
||||||
|
)
|
||||||
|
value = Column(String)
|
||||||
|
|
||||||
|
__mapper_args__ = {
|
||||||
|
'polymorphic_identity': __tablename__,
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_types_registry['RawSensor'] = RawSensor
|
||||||
|
else:
|
||||||
|
RawSensor = entity_types_registry['RawSensor']
|
||||||
|
|
||||||
|
|
||||||
|
if not entity_types_registry.get('NumericSensor'):
|
||||||
|
|
||||||
|
class NumericSensor(Device):
|
||||||
|
__tablename__ = 'numeric_sensor'
|
||||||
|
|
||||||
|
id = Column(
|
||||||
|
Integer, ForeignKey(Device.id, ondelete='CASCADE'), primary_key=True
|
||||||
|
)
|
||||||
|
value = Column(Numeric)
|
||||||
|
min = Column(Numeric)
|
||||||
|
max = Column(Numeric)
|
||||||
|
|
||||||
|
__mapper_args__ = {
|
||||||
|
'polymorphic_identity': __tablename__,
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_types_registry['NumericSensor'] = NumericSensor
|
||||||
|
else:
|
||||||
|
NumericSensor = entity_types_registry['NumericSensor']
|
|
@ -2,13 +2,14 @@ from abc import ABC, abstractmethod
|
||||||
from typing import Any, Dict, Optional, List, Union
|
from typing import Any, Dict, Optional, List, Union
|
||||||
|
|
||||||
from platypush.entities import manages
|
from platypush.entities import manages
|
||||||
|
from platypush.entities.batteries import Battery
|
||||||
from platypush.entities.dimmers import Dimmer
|
from platypush.entities.dimmers import Dimmer
|
||||||
from platypush.entities.lights import Light
|
from platypush.entities.lights import Light
|
||||||
from platypush.entities.switches import Switch
|
from platypush.entities.switches import Switch
|
||||||
from platypush.plugins import Plugin, action
|
from platypush.plugins import Plugin, action
|
||||||
|
|
||||||
|
|
||||||
@manages(Dimmer, Light, Switch)
|
@manages(Battery, Dimmer, Light, Switch)
|
||||||
class ZwaveBasePlugin(Plugin, ABC):
|
class ZwaveBasePlugin(Plugin, ABC):
|
||||||
"""
|
"""
|
||||||
Base class for Z-Wave plugins.
|
Base class for Z-Wave plugins.
|
||||||
|
|
|
@ -6,6 +6,7 @@ from datetime import datetime
|
||||||
from threading import Timer
|
from threading import Timer
|
||||||
from typing import Optional, List, Any, Dict, Union, Iterable, Mapping, Callable
|
from typing import Optional, List, Any, Dict, Union, Iterable, Mapping, Callable
|
||||||
|
|
||||||
|
from platypush.entities.batteries import Battery
|
||||||
from platypush.entities.dimmers import Dimmer
|
from platypush.entities.dimmers import Dimmer
|
||||||
from platypush.entities.switches import Switch
|
from platypush.entities.switches import Switch
|
||||||
from platypush.message.event.zwave import ZwaveNodeRenamedEvent, ZwaveNodeEvent
|
from platypush.message.event.zwave import ZwaveNodeRenamedEvent, ZwaveNodeEvent
|
||||||
|
@ -482,6 +483,14 @@ class ZwaveMqttPlugin(MqttPlugin, ZwaveBasePlugin):
|
||||||
value, 'switch_multilevel', 'switch_toggle_multilevel'
|
value, 'switch_multilevel', 'switch_toggle_multilevel'
|
||||||
) and not value.get('is_read_only')
|
) and not value.get('is_read_only')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _is_battery(cls, value: Mapping):
|
||||||
|
return (
|
||||||
|
cls._matches_classes(value, 'battery')
|
||||||
|
and value.get('is_read_only')
|
||||||
|
and not value['id'].endswith('-isLow')
|
||||||
|
)
|
||||||
|
|
||||||
def _to_entity_args(self, value: Mapping) -> dict:
|
def _to_entity_args(self, value: Mapping) -> dict:
|
||||||
if value['id'].endswith('-targetValue'):
|
if value['id'].endswith('-targetValue'):
|
||||||
current_value_id = '-'.join(value['id'].split('-')[:-1] + ['currentValue'])
|
current_value_id = '-'.join(value['id'].split('-')[:-1] + ['currentValue'])
|
||||||
|
@ -525,6 +534,12 @@ class ZwaveMqttPlugin(MqttPlugin, ZwaveBasePlugin):
|
||||||
entity_args['value'] = value['data']
|
entity_args['value'] = value['data']
|
||||||
entity_args['min'] = value['min']
|
entity_args['min'] = value['min']
|
||||||
entity_args['max'] = value['max']
|
entity_args['max'] = value['max']
|
||||||
|
elif self._is_battery(value):
|
||||||
|
entity_type = Battery
|
||||||
|
entity_args['value'] = value['data']
|
||||||
|
entity_args['min'] = value['min']
|
||||||
|
entity_args['max'] = value['max']
|
||||||
|
entity_args['unit'] = value.get('units', '%')
|
||||||
elif self._is_switch(value):
|
elif self._is_switch(value):
|
||||||
entity_type = Switch
|
entity_type = Switch
|
||||||
entity_args['state'] = value['data']
|
entity_args['state'] = value['data']
|
||||||
|
|
Loading…
Reference in a new issue