Cleaned up ISY994 light and sensor code to use the same abstract class.

This commit is contained in:
Ryan Kraus 2015-04-12 16:45:23 -04:00
parent 57f27cc97a
commit f6d75f2db2
3 changed files with 141 additions and 156 deletions

View File

@ -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
import logging
@ -14,26 +15,27 @@ from homeassistant.loader import get_component
from homeassistant.helpers import validate_config
from homeassistant.helpers.entity import ToggleEntity
from homeassistant.const import (
CONF_HOST, CONF_USERNAME, CONF_PASSWORD,
EVENT_PLATFORM_DISCOVERED,
CONF_HOST, CONF_USERNAME, CONF_PASSWORD, EVENT_PLATFORM_DISCOVERED,
ATTR_SERVICE, ATTR_DISCOVERED, ATTR_FRIENDLY_NAME)
# homeassistant constants
DOMAIN = "isy994"
DEPENDENCIES = []
DISCOVER_LIGHTS = "isy994.lights"
#DISCOVER_SWITCHES = "isy994.switches"
# DISCOVER_SWITCHES = "isy994.switches"
DISCOVER_SENSORS = "isy994.sensors"
ISY = None
def setup(hass, config):
""" Sets up the ISY994 component. """
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# setup logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
def setup(hass, config):
# pull values from configuration file
if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]}, logger):
if not validate_config(config,
{DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]},
logger):
return False
else:
user = config[DOMAIN][CONF_USERNAME]
@ -47,8 +49,8 @@ def setup(hass, config):
addr = addr.replace('https://', '')
https = True
else:
logger.error('isy994 host value in configuration ' +
'file is invalid.')
logger.error('isy994 host value in configuration ' +
'file is invalid.')
return False
port = host.port
addr = addr.replace(':{}'.format(port), '')
@ -64,11 +66,107 @@ def setup(hass, config):
('light', DISCOVER_LIGHTS))):
component = get_component(comp_name)
bootstrap.setup_component(hass, component.DOMAIN, config)
hass.bus.fire(EVENT_PLATFORM_DISCOVERED,
{
ATTR_SERVICE: discovery,
ATTR_DISCOVERED: {}
})
hass.bus.fire(EVENT_PLATFORM_DISCOVERED,
{ATTR_SERVICE: discovery,
ATTR_DISCOVERED: {}})
ISY.auto_update = 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

View File

@ -1,17 +1,15 @@
""" Support for ISY994 sensors. """
""" Support for ISY994 lights. """
# system imports
import logging
# homeassistant imports
from ..isy994 import ISY
from homeassistant.helpers.entity import ToggleEntity
from homeassistant.const import STATE_ON, STATE_OFF
from homeassistant.components.isy994 import ISYDeviceABC, ISY
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):
""" Sets up the isy994 platform. """
print('************ RUNNING')
logger = logging.getLogger(__name__)
devs = []
# verify connection
@ -27,67 +25,11 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
add_devices(devs)
class ISYLightDevice(ToggleEntity):
class ISYLightDevice(ISYDeviceABC):
""" represents as isy light within home assistant. """
domain = 'light'
def __init__(self, node):
# setup properties
self.node = node
#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()
_domain = 'light'
_dtype = 'analog'
_attrs = {ATTR_BRIGHTNESS: 'value'}
_onattrs = [ATTR_BRIGHTNESS]
_states = [STATE_ON, STATE_OFF]

View File

@ -3,7 +3,7 @@
import logging
# homeassistant imports
from ..isy994 import ISY
from homeassistant.components.isy994 import ISY, ISYDeviceABC
from homeassistant.helpers.entity import Entity
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:
for prop in ISY.climate._id2name:
if prop is not None:
devs.append(ISYSensorDevice('ISY.weather.' + prop, prop,
getattr(ISY.climate, prop),
getattr(ISY.climate, prop + '_units')))
node = WeatherPseudoNode('ISY.weather.' + prop, prop,
getattr(ISY.climate, prop),
getattr(ISY.climate, prop + '_units'))
devs.append(ISYSensorDevice(node))
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. """
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()
_domain = 'sensor'