Cleaned up ISY994 light and sensor code to use the same abstract class.
This commit is contained in:
parent
57f27cc97a
commit
f6d75f2db2
3 changed files with 141 additions and 156 deletions
|
@ -1,5 +1,6 @@
|
||||||
"""
|
"""
|
||||||
Connects to an ISY-994 controller and loads relevant components to control its devices.
|
Connects to an ISY-994 controller and loads relevant components to control its
|
||||||
|
devices. Also contains the base classes for ISY Sensors, Lights, and Switches.
|
||||||
"""
|
"""
|
||||||
# system imports
|
# system imports
|
||||||
import logging
|
import logging
|
||||||
|
@ -14,26 +15,27 @@ from homeassistant.loader import get_component
|
||||||
from homeassistant.helpers import validate_config
|
from homeassistant.helpers import validate_config
|
||||||
from homeassistant.helpers.entity import ToggleEntity
|
from homeassistant.helpers.entity import ToggleEntity
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_HOST, CONF_USERNAME, CONF_PASSWORD,
|
CONF_HOST, CONF_USERNAME, CONF_PASSWORD, EVENT_PLATFORM_DISCOVERED,
|
||||||
EVENT_PLATFORM_DISCOVERED,
|
|
||||||
ATTR_SERVICE, ATTR_DISCOVERED, ATTR_FRIENDLY_NAME)
|
ATTR_SERVICE, ATTR_DISCOVERED, ATTR_FRIENDLY_NAME)
|
||||||
|
|
||||||
# homeassistant constants
|
# homeassistant constants
|
||||||
DOMAIN = "isy994"
|
DOMAIN = "isy994"
|
||||||
DEPENDENCIES = []
|
DEPENDENCIES = []
|
||||||
DISCOVER_LIGHTS = "isy994.lights"
|
DISCOVER_LIGHTS = "isy994.lights"
|
||||||
#DISCOVER_SWITCHES = "isy994.switches"
|
# DISCOVER_SWITCHES = "isy994.switches"
|
||||||
DISCOVER_SENSORS = "isy994.sensors"
|
DISCOVER_SENSORS = "isy994.sensors"
|
||||||
ISY = None
|
ISY = None
|
||||||
|
|
||||||
def setup(hass, config):
|
# setup logger
|
||||||
""" Sets up the ISY994 component. """
|
logger = logging.getLogger(__name__)
|
||||||
logger = logging.getLogger(__name__)
|
logger.setLevel(logging.DEBUG)
|
||||||
logger.setLevel(logging.DEBUG)
|
|
||||||
|
|
||||||
|
|
||||||
|
def setup(hass, config):
|
||||||
# pull values from configuration file
|
# pull values from configuration file
|
||||||
if not validate_config(config,
|
if not validate_config(config,
|
||||||
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]}, logger):
|
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
|
||||||
|
logger):
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
user = config[DOMAIN][CONF_USERNAME]
|
user = config[DOMAIN][CONF_USERNAME]
|
||||||
|
@ -47,8 +49,8 @@ def setup(hass, config):
|
||||||
addr = addr.replace('https://', '')
|
addr = addr.replace('https://', '')
|
||||||
https = True
|
https = True
|
||||||
else:
|
else:
|
||||||
logger.error('isy994 host value in configuration ' +
|
logger.error('isy994 host value in configuration ' +
|
||||||
'file is invalid.')
|
'file is invalid.')
|
||||||
return False
|
return False
|
||||||
port = host.port
|
port = host.port
|
||||||
addr = addr.replace(':{}'.format(port), '')
|
addr = addr.replace(':{}'.format(port), '')
|
||||||
|
@ -64,11 +66,107 @@ def setup(hass, config):
|
||||||
('light', DISCOVER_LIGHTS))):
|
('light', DISCOVER_LIGHTS))):
|
||||||
component = get_component(comp_name)
|
component = get_component(comp_name)
|
||||||
bootstrap.setup_component(hass, component.DOMAIN, config)
|
bootstrap.setup_component(hass, component.DOMAIN, config)
|
||||||
hass.bus.fire(EVENT_PLATFORM_DISCOVERED,
|
hass.bus.fire(EVENT_PLATFORM_DISCOVERED,
|
||||||
{
|
{ATTR_SERVICE: discovery,
|
||||||
ATTR_SERVICE: discovery,
|
ATTR_DISCOVERED: {}})
|
||||||
ATTR_DISCOVERED: {}
|
|
||||||
})
|
|
||||||
|
|
||||||
ISY.auto_update = True
|
ISY.auto_update = True
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class ISYDeviceABC(ToggleEntity):
|
||||||
|
""" Abstract Class for an ISY device within home assistant. """
|
||||||
|
|
||||||
|
_attrs = {}
|
||||||
|
_onattrs = []
|
||||||
|
_states = []
|
||||||
|
_dtype = None
|
||||||
|
_domain = None
|
||||||
|
|
||||||
|
def __init__(self, node):
|
||||||
|
# setup properties
|
||||||
|
self.node = node
|
||||||
|
|
||||||
|
# track changes
|
||||||
|
self._changeHandler = self.node.status. \
|
||||||
|
subscribe('changed', self.onUpdate)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
""" cleanup subscriptions because it is the right thing to do. """
|
||||||
|
self._changeHandler.unsubscribe()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def domain(self):
|
||||||
|
return self._domain
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dtype(self):
|
||||||
|
if self._dtype in ['analog', 'binary']:
|
||||||
|
return self._dtype
|
||||||
|
return 'binary' if self._units is None else 'analog'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def should_poll(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
""" returns the unclean value from the controller """
|
||||||
|
return self.node.status._val
|
||||||
|
|
||||||
|
@property
|
||||||
|
def state_attributes(self):
|
||||||
|
attr = {ATTR_FRIENDLY_NAME: self.name}
|
||||||
|
for name, prop in self._attrs.items():
|
||||||
|
attr[name] = getattr(self, prop)
|
||||||
|
return attr
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_id(self):
|
||||||
|
""" Returns the id of this isy sensor """
|
||||||
|
return self.node._id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
""" Returns the name of the node if any. """
|
||||||
|
return self.node.name
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
""" Update state of the sensor. """
|
||||||
|
# ISY objects are automatically updated by the ISY's event stream
|
||||||
|
pass
|
||||||
|
|
||||||
|
def onUpdate(self, e):
|
||||||
|
""" Handles the update recieved event. """
|
||||||
|
self.update_ha_state()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_on(self):
|
||||||
|
return self.value > 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_open(self):
|
||||||
|
return self.is_on
|
||||||
|
|
||||||
|
@property
|
||||||
|
def state(self):
|
||||||
|
""" Returns the state of the node. """
|
||||||
|
if len(self._states) > 0:
|
||||||
|
return self._states[0] if self.is_on else self._states[1]
|
||||||
|
return self.value
|
||||||
|
|
||||||
|
def turn_on(self, **kwargs):
|
||||||
|
""" turns the device on """
|
||||||
|
attrs = [kwargs.get(name) for name in self._onattrs]
|
||||||
|
self.node.on(*attrs)
|
||||||
|
|
||||||
|
def turn_off(self, **kwargs):
|
||||||
|
""" turns the device off """
|
||||||
|
self.node.off()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unit_of_measurement(self):
|
||||||
|
try:
|
||||||
|
return self.node.units
|
||||||
|
except AttributeError:
|
||||||
|
return None
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
""" Support for ISY994 sensors. """
|
""" Support for ISY994 lights. """
|
||||||
# system imports
|
# system imports
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
# homeassistant imports
|
# homeassistant imports
|
||||||
from ..isy994 import ISY
|
from homeassistant.components.isy994 import ISYDeviceABC, ISY
|
||||||
from homeassistant.helpers.entity import ToggleEntity
|
|
||||||
from homeassistant.const import STATE_ON, STATE_OFF
|
|
||||||
from homeassistant.components.light import ATTR_BRIGHTNESS
|
from homeassistant.components.light import ATTR_BRIGHTNESS
|
||||||
|
from homeassistant.const import STATE_ON, STATE_OFF
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
""" Sets up the isy994 platform. """
|
""" Sets up the isy994 platform. """
|
||||||
print('************ RUNNING')
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
devs = []
|
devs = []
|
||||||
# verify connection
|
# verify connection
|
||||||
|
@ -27,67 +25,11 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
add_devices(devs)
|
add_devices(devs)
|
||||||
|
|
||||||
|
|
||||||
class ISYLightDevice(ToggleEntity):
|
class ISYLightDevice(ISYDeviceABC):
|
||||||
""" represents as isy light within home assistant. """
|
""" represents as isy light within home assistant. """
|
||||||
|
|
||||||
domain = 'light'
|
_domain = 'light'
|
||||||
|
_dtype = 'analog'
|
||||||
def __init__(self, node):
|
_attrs = {ATTR_BRIGHTNESS: 'value'}
|
||||||
# setup properties
|
_onattrs = [ATTR_BRIGHTNESS]
|
||||||
self.node = node
|
_states = [STATE_ON, STATE_OFF]
|
||||||
#self.entity_id = self.domain + '.' + self.name.replace(' ', '_')
|
|
||||||
|
|
||||||
# track changes
|
|
||||||
self._changeHandler = self.node.status. \
|
|
||||||
subscribe('changed', self.onUpdate)
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
self._changeHandler.unsubscribe()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def should_poll(self):
|
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
|
||||||
def dtype(self):
|
|
||||||
return 'analog'
|
|
||||||
|
|
||||||
@property
|
|
||||||
def value(self):
|
|
||||||
""" return the integer setting of the light (brightness) """
|
|
||||||
return self.node.status._val
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_on(self):
|
|
||||||
return self.value > 0
|
|
||||||
|
|
||||||
@property
|
|
||||||
def state_attributes(self):
|
|
||||||
return {ATTR_BRIGHTNESS: self.value}
|
|
||||||
|
|
||||||
@property
|
|
||||||
def unique_id(self):
|
|
||||||
""" Returns the id of this isy sensor """
|
|
||||||
return self.node._id
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
""" Returns the name of the sensor if any. """
|
|
||||||
return self.node.name
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
""" Update state of the sensor. """
|
|
||||||
# ISY objects are automatically updated by the ISY's event stream
|
|
||||||
pass
|
|
||||||
|
|
||||||
def onUpdate(self, e):
|
|
||||||
self.update_ha_state()
|
|
||||||
|
|
||||||
def turn_on(self, **kwargs):
|
|
||||||
""" turns the device on """
|
|
||||||
brightness = kwargs.get(ATTR_BRIGHTNESS)
|
|
||||||
self.node.on(brightness)
|
|
||||||
|
|
||||||
def turn_off(self, **kwargs):
|
|
||||||
""" turns the device off """
|
|
||||||
self.node.off()
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
# homeassistant imports
|
# homeassistant imports
|
||||||
from ..isy994 import ISY
|
from homeassistant.components.isy994 import ISY, ISYDeviceABC
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.const import STATE_OPEN, STATE_CLOSED
|
from homeassistant.const import STATE_OPEN, STATE_CLOSED
|
||||||
|
|
||||||
|
@ -21,80 +21,25 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
if ISY.climate is not None:
|
if ISY.climate is not None:
|
||||||
for prop in ISY.climate._id2name:
|
for prop in ISY.climate._id2name:
|
||||||
if prop is not None:
|
if prop is not None:
|
||||||
devs.append(ISYSensorDevice('ISY.weather.' + prop, prop,
|
node = WeatherPseudoNode('ISY.weather.' + prop, prop,
|
||||||
getattr(ISY.climate, prop),
|
getattr(ISY.climate, prop),
|
||||||
getattr(ISY.climate, prop + '_units')))
|
getattr(ISY.climate, prop + '_units'))
|
||||||
|
devs.append(ISYSensorDevice(node))
|
||||||
|
|
||||||
add_devices(devs)
|
add_devices(devs)
|
||||||
|
|
||||||
|
|
||||||
class ISYSensorDevice(Entity):
|
class WeatherPseudoNode(object):
|
||||||
|
""" This class allows weather variable to act as regular nodes. """
|
||||||
|
|
||||||
|
def __init__(self, device_id, name, status, units=None):
|
||||||
|
self._id = device_id
|
||||||
|
self.name = name
|
||||||
|
self.status = status
|
||||||
|
self.units = units
|
||||||
|
|
||||||
|
|
||||||
|
class ISYSensorDevice(ISYDeviceABC):
|
||||||
""" represents a isy sensor within home assistant. """
|
""" represents a isy sensor within home assistant. """
|
||||||
|
|
||||||
domain = 'sensor'
|
_domain = 'sensor'
|
||||||
|
|
||||||
def __init__(self, device_id, name, source, units=None):
|
|
||||||
# setup properties
|
|
||||||
self._id = device_id
|
|
||||||
self._name = name
|
|
||||||
self.entity_id = self.domain + '.' + self.name.replace(' ', '_')
|
|
||||||
self._source = source
|
|
||||||
self._units = units
|
|
||||||
|
|
||||||
# track changes
|
|
||||||
self._changeHandler = self._source.subscribe('changed', self.onUpdate)
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
self._changeHandler.unsubscribe()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def should_poll(self):
|
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
|
||||||
def dtype(self):
|
|
||||||
return 'binary' if self._units is None else 'analog'
|
|
||||||
|
|
||||||
@property
|
|
||||||
def state(self):
|
|
||||||
""" Returns the state. """
|
|
||||||
if self.dtype is 'binary':
|
|
||||||
return STATE_OPEN if self.is_open >= 255 else STATE_CLOSED
|
|
||||||
else:
|
|
||||||
return self.value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def state_attributes(self):
|
|
||||||
return {}
|
|
||||||
|
|
||||||
@property
|
|
||||||
def unit_of_measurement(self):
|
|
||||||
return self._units
|
|
||||||
|
|
||||||
@property
|
|
||||||
def unique_id(self):
|
|
||||||
""" Returns the id of this isy sensor """
|
|
||||||
return self._id
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
""" Returns the name of the sensor if any. """
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
""" Update state of the sensor. """
|
|
||||||
# ISY objects are automatically updated by the ISY's event stream
|
|
||||||
pass
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_open(self):
|
|
||||||
""" True if door is open. """
|
|
||||||
return self.value >= 255
|
|
||||||
|
|
||||||
@property
|
|
||||||
def value(self):
|
|
||||||
return self._source._val
|
|
||||||
|
|
||||||
def onUpdate(self, e):
|
|
||||||
self.update_ha_state()
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue