diff --git a/homeassistant/components/isy994.py b/homeassistant/components/isy994.py new file mode 100644 index 00000000000..7a556d565e3 --- /dev/null +++ b/homeassistant/components/isy994.py @@ -0,0 +1,73 @@ +""" +Connects to an ISY-994 controller and loads relevant components to control its devices. +""" +# system imports +import logging +from urllib.parse import urlparse + +# addon library imports +import PyISY + +# homeassistant imports +from homeassistant import bootstrap +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, + ATTR_SERVICE, ATTR_DISCOVERED, ATTR_FRIENDLY_NAME) + +# homeassistant constants +DOMAIN = "isy994" +DEPENDENCIES = [] +#DISCOVER_LIGHTS = "isy994.lights" +#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) + + # pull values from configuration file + if not validate_config(config, + {DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]}, logger): + return False + else: + user = config[DOMAIN][CONF_USERNAME] + password = config[DOMAIN][CONF_PASSWORD] + host = urlparse(config[DOMAIN][CONF_HOST]) + addr = host.geturl() + if host.scheme == 'http': + addr = addr.replace('http://', '') + https = False + elif host.scheme == 'https': + addr = addr.replace('https://', '') + https = True + else: + logger.error('isy994 host value in configuration ' + + 'file is invalid.') + return False + port = host.port + addr = addr.replace(':{}'.format(port), '') + + # connect to ISY controller + global ISY + ISY = PyISY.ISY(addr, port, user, password, use_https=https, log=logger) + if not ISY.connected: + return False + + # Load components for the devices in the ISY controller that we support + for comp_name, discovery in ((('sensor', DISCOVER_SENSORS),)): + component = get_component(comp_name) + bootstrap.setup_component(hass, component.DOMAIN, config) + hass.bus.fire(EVENT_PLATFORM_DISCOVERED, + { + ATTR_SERVICE: discovery, + ATTR_DISCOVERED: {} + }) + + ISY.auto_update = True + return True diff --git a/homeassistant/components/sensor/__init__.py b/homeassistant/components/sensor/__init__.py index 8248651710a..5cbd07d0e59 100644 --- a/homeassistant/components/sensor/__init__.py +++ b/homeassistant/components/sensor/__init__.py @@ -6,7 +6,7 @@ Component to interface with various sensors that can be monitored. import logging from homeassistant.helpers.entity_component import EntityComponent -from homeassistant.components import wink, zwave +from homeassistant.components import wink, zwave, isy994 DOMAIN = 'sensor' DEPENDENCIES = [] @@ -18,6 +18,7 @@ ENTITY_ID_FORMAT = DOMAIN + '.{}' DISCOVERY_PLATFORMS = { wink.DISCOVER_SENSORS: 'wink', zwave.DISCOVER_SENSORS: 'zwave', + isy994.DISCOVER_SENSORS: 'isy994' } diff --git a/homeassistant/components/sensor/isy994.py b/homeassistant/components/sensor/isy994.py new file mode 100644 index 00000000000..66f5eb84fab --- /dev/null +++ b/homeassistant/components/sensor/isy994.py @@ -0,0 +1,100 @@ +""" Support for ISY994 sensors. """ +# system imports +import logging + +# homeassistant imports +from ..isy994 import ISY +from homeassistant.helpers.entity import Entity +from homeassistant.const import STATE_OPEN, STATE_CLOSED + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """ Sets up the isy994 platform. """ + logger = logging.getLogger(__name__) + devs = [] + # verify connection + if ISY is None or not ISY.connected: + logger.error('A connection has not been made to the ISY controller.') + return False + + # import weather + 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'))) + + + add_devices(devs) + + +class ISYSensorDevice(Entity): + """ 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()