diff --git a/homeassistant/components/isy994.py b/homeassistant/components/isy994.py index 84299cef6a6508f5fd63024bbaef78cf3bafeb89..fe5d5516cb64c93dffc6a5e53986df36a59a91db 100644 --- a/homeassistant/components/isy994.py +++ b/homeassistant/components/isy994.py @@ -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 diff --git a/homeassistant/components/light/isy994.py b/homeassistant/components/light/isy994.py index 3f4989554873a6d7419abeba34dbda6c3c73770c..16d7f6b052c33e3dbb7c537e550b683f3cd6c1cf 100644 --- a/homeassistant/components/light/isy994.py +++ b/homeassistant/components/light/isy994.py @@ -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] diff --git a/homeassistant/components/sensor/isy994.py b/homeassistant/components/sensor/isy994.py index 66f5eb84faba625ccad8c3074a9fc235d2c0baf6..3d007724219e8a0bba30bfdeb183e47da366bc35 100644 --- a/homeassistant/components/sensor/isy994.py +++ b/homeassistant/components/sensor/isy994.py @@ -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): - """ represents a isy sensor within home assistant. """ - - domain = 'sensor' +class WeatherPseudoNode(object): + """ This class allows weather variable to act as regular nodes. """ - def __init__(self, device_id, name, source, units=None): - # setup properties + def __init__(self, device_id, name, status, units=None): 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' + self.name = name + self.status = status + self.units = units - @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 +class ISYSensorDevice(ISYDeviceABC): + """ represents a isy sensor within home assistant. """ - def onUpdate(self, e): - self.update_ha_state() + _domain = 'sensor'