appd - Completed redesign of entity manager
This commit is contained in:
6
appdaemon/apps/helpers/base.py
Normal file
6
appdaemon/apps/helpers/base.py
Normal file
@@ -0,0 +1,6 @@
|
||||
import appdaemon.plugins.hass.hassapi as hass
|
||||
|
||||
class Base(hass.Hass):
|
||||
def initialize(self):
|
||||
if(getattr(super(), 'initialize', False)):
|
||||
super().initialize()
|
||||
152
appdaemon/apps/helpers/entities.py
Normal file
152
appdaemon/apps/helpers/entities.py
Normal file
@@ -0,0 +1,152 @@
|
||||
import base
|
||||
|
||||
class Entities(base.Base):
|
||||
|
||||
def initialize(self):
|
||||
if(getattr(super(), 'initialize', False)):
|
||||
super().initialize()
|
||||
self.e = {}
|
||||
|
||||
def register_entity(self, name, entity, managed=False, default=None, attributes=None):
|
||||
domain, _ = entity.split('.')
|
||||
controller = {
|
||||
'light': LightEntity,
|
||||
'switch': SwitchEntity,
|
||||
'input_number': InputNumberEntity,
|
||||
'input_datetime': InputDateTimeEntity,
|
||||
'input_select': InputSelectEntity,
|
||||
}.get(domain, Entity)
|
||||
self.e[name] = controller(self, entity, managed, default, attributes)
|
||||
|
||||
|
||||
class Entity:
|
||||
|
||||
def __init__(self, hass, entity, managed=False, state=None, attributes=None):
|
||||
self._hass = hass
|
||||
self._entity = entity
|
||||
self._managed = managed
|
||||
self._state = state
|
||||
self._laststate = None
|
||||
self._attributes = attributes
|
||||
self._listeners = []
|
||||
|
||||
hass.listen_state(self._listener, entity=entity, attribute='all')
|
||||
|
||||
if managed:
|
||||
self.push()
|
||||
hass.listen_event(self._service_listener, event = 'call_service')
|
||||
else:
|
||||
self.pull()
|
||||
|
||||
# State change listeners
|
||||
def listen(self, callback, kwarg=None):
|
||||
self._listeners.append({
|
||||
'callback': callback,
|
||||
'kwarg': kwarg,
|
||||
})
|
||||
return self._listeners[-1]
|
||||
|
||||
def unlisten(self, handle):
|
||||
if handle in self._listeners:
|
||||
self._listeners.remove(handle)
|
||||
|
||||
def _listener(self, entity, attribute, old, new, kwargs):
|
||||
self._state = new['state']
|
||||
self._attributes = new['attributes']
|
||||
old, new = self._laststate, self._state
|
||||
if old != new:
|
||||
self._laststate = new
|
||||
self._callback(old, new)
|
||||
|
||||
def _callback(self, old, new):
|
||||
for l in self._listeners:
|
||||
l['callback'](old, new, l['kwarg'])
|
||||
pass
|
||||
|
||||
# Updating state
|
||||
def pull(self):
|
||||
d = self._hass.get_state(self._entity, attribute='all')
|
||||
self._state = d['state']
|
||||
self._laststate = self._state
|
||||
self._attributes = d['attributes']
|
||||
|
||||
def push(self):
|
||||
self._hass.set_state(self._entity, state=self._state, attributes=self._attributes)
|
||||
if self._state != self._laststate:
|
||||
old = self._laststate
|
||||
new = self._state
|
||||
self._laststate = new
|
||||
self.set_state(old, new)
|
||||
self._callback(old, new)
|
||||
|
||||
def set_state(self, old, new):
|
||||
pass
|
||||
|
||||
# If the entity is controller by appd, changes made in the GUI will be communicated via service calls
|
||||
def _service_listener(self, event, data, kwarg):
|
||||
if data['service_data'].get('entity_id', '') == self._entity:
|
||||
self.service_callback(data)
|
||||
|
||||
def service_callback(self, data):
|
||||
pass
|
||||
|
||||
#
|
||||
@property
|
||||
def state(self):
|
||||
return self._state
|
||||
@state.setter
|
||||
def state(self, value):
|
||||
self._state = value
|
||||
|
||||
@property
|
||||
def attr(self):
|
||||
return self._attributes
|
||||
|
||||
|
||||
class LightEntity(Entity):
|
||||
|
||||
def set_state(self, old, new):
|
||||
if new == "on":
|
||||
self._hass.call_service("light/turn_on", entity_id = self._entity)
|
||||
elif new == "off":
|
||||
self._hass.call_service("light/turn_off", entity_id = self._entity)
|
||||
|
||||
|
||||
class SwitchEntity(Entity):
|
||||
|
||||
def service_callback(self, data):
|
||||
if data['service'] == 'turn_on':
|
||||
self._state = "on"
|
||||
if data['service'] == 'turn_off':
|
||||
self._state = "off"
|
||||
self.push()
|
||||
|
||||
|
||||
class InputNumberEntity(Entity):
|
||||
|
||||
def service_callback(self, data):
|
||||
if data['domain'] == 'input_number' and data['service'] == 'set_value':
|
||||
self._state = data['service_data']['value']
|
||||
self.push()
|
||||
|
||||
class InputDateTimeEntity(Entity):
|
||||
|
||||
def set_state(self, old, new):
|
||||
time = new.split(':')
|
||||
time += ["00"] * (3 - len(time))
|
||||
self._state = ':'.join(time)
|
||||
self.attr['hour'] = int(time[0], base=10)
|
||||
self.attr['minute'] = int(time[1], base=10)
|
||||
self.attr['seconf'] = int(time[2], base=10)
|
||||
|
||||
def service_callback(self, data):
|
||||
if data['service'] == 'set_datetime':
|
||||
self._state = data['service_data'].get('time', "00:00:00")
|
||||
self.push()
|
||||
|
||||
class InputSelectEntity(Entity):
|
||||
|
||||
def service_callback(self, data):
|
||||
if data['service'] == 'select_option':
|
||||
self._state = data['service_data'].get('option', None)
|
||||
self.push()
|
||||
4
appdaemon/apps/helpers/helpers.yaml
Normal file
4
appdaemon/apps/helpers/helpers.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
global_modules:
|
||||
- base
|
||||
- entities
|
||||
- timers
|
||||
42
appdaemon/apps/helpers/timers.py
Normal file
42
appdaemon/apps/helpers/timers.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import base
|
||||
|
||||
class Timers(base.Base):
|
||||
def initialize(self):
|
||||
if(getattr(super(), 'initialize', False)):
|
||||
super().initialize()
|
||||
self._timers = {}
|
||||
|
||||
functions = [
|
||||
'run_in',
|
||||
'run_once',
|
||||
'run_at',
|
||||
'run_daily',
|
||||
'run_hourly',
|
||||
'run_minutely',
|
||||
'run_every',
|
||||
'run_at_sunrise',
|
||||
'run_at_sunset',
|
||||
]
|
||||
for f in functions:
|
||||
self._override(f)
|
||||
|
||||
setattr(self, '_cancel_timer', super().cancel_timer)
|
||||
|
||||
def cancel_timer(self, name, *args, **kwargs):
|
||||
if type(name) is str:
|
||||
if name in self._timers:
|
||||
return super().cancel_timer(self._timers[name])
|
||||
else:
|
||||
return super().cancel_timer(*args, **kwargs)
|
||||
|
||||
def _override(self, f):
|
||||
setattr(self, f'_{f}', getattr(self, f))
|
||||
def fn(name, *args, **kwargs):
|
||||
if type(name) is str:
|
||||
if name in self._timers:
|
||||
super().cancel_timer(self._timers[name])
|
||||
self._timers[name] = getattr(self, f'_{f}')(*args, **kwargs)
|
||||
return self._timers[name]
|
||||
else:
|
||||
return getattr(self, f'_{f}')(name, *args, **kwargs)
|
||||
setattr(self, f, fn)
|
||||
Reference in New Issue
Block a user