diff --git a/.coveragerc b/.coveragerc index 2b846ca5b09..dd3874a9ffd 100644 --- a/.coveragerc +++ b/.coveragerc @@ -182,6 +182,9 @@ omit = homeassistant/components/tado.py homeassistant/components/*/tado.py + homeassistant/components/tahoma.py + homeassistant/components/*/tahoma.py + homeassistant/components/tellduslive.py homeassistant/components/*/tellduslive.py diff --git a/CODEOWNERS b/CODEOWNERS index 82ae451e59c..66007f53d7e 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -68,6 +68,8 @@ homeassistant/components/velux.py @Julius2342 homeassistant/components/*/velux.py @Julius2342 homeassistant/components/knx.py @Julius2342 homeassistant/components/*/knx.py @Julius2342 +homeassistant/components/tahoma.py @philklei +homeassistant/components/*/tahoma.py @philklei homeassistant/components/tesla.py @zabuldon homeassistant/components/*/tesla.py @zabuldon homeassistant/components/*/tradfri.py @ggravlingen diff --git a/homeassistant/components/cover/tahoma.py b/homeassistant/components/cover/tahoma.py new file mode 100644 index 00000000000..ce668cfe876 --- /dev/null +++ b/homeassistant/components/cover/tahoma.py @@ -0,0 +1,73 @@ +""" +Support for Tahoma cover - shutters etc. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/cover.tahoma/ +""" +import logging + +from homeassistant.components.cover import CoverDevice, ENTITY_ID_FORMAT +from homeassistant.components.tahoma import ( + DOMAIN as TAHOMA_DOMAIN, TahomaDevice) + +DEPENDENCIES = ['tahoma'] + +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up Tahoma covers.""" + controller = hass.data[TAHOMA_DOMAIN]['controller'] + devices = [] + for device in hass.data[TAHOMA_DOMAIN]['devices']['cover']: + devices.append(TahomaCover(device, controller)) + add_devices(devices, True) + + +class TahomaCover(TahomaDevice, CoverDevice): + """Representation a Tahoma Cover.""" + + def __init__(self, tahoma_device, controller): + """Initialize the Tahoma device.""" + super().__init__(tahoma_device, controller) + self.entity_id = ENTITY_ID_FORMAT.format(self.unique_id) + + def update(self): + """Update method.""" + self.controller.get_states([self.tahoma_device]) + + @property + def current_cover_position(self): + """ + Return current position of cover. + + 0 is closed, 100 is fully open. + """ + position = 100 - self.tahoma_device.active_states['core:ClosureState'] + if position <= 5: + return 0 + if position >= 95: + return 100 + return position + + def set_cover_position(self, position, **kwargs): + """Move the cover to a specific position.""" + self.apply_action('setPosition', 100 - position) + + @property + def is_closed(self): + """Return if the cover is closed.""" + if self.current_cover_position is not None: + return self.current_cover_position == 0 + + def open_cover(self, **kwargs): + """Open the cover.""" + self.apply_action('open') + + def close_cover(self, **kwargs): + """Close the cover.""" + self.apply_action('close') + + def stop_cover(self, **kwargs): + """Stop the cover.""" + self.apply_action('stopIdentify') diff --git a/homeassistant/components/sensor/tahoma.py b/homeassistant/components/sensor/tahoma.py new file mode 100644 index 00000000000..d0b038fd230 --- /dev/null +++ b/homeassistant/components/sensor/tahoma.py @@ -0,0 +1,61 @@ +""" +Support for Tahoma sensors. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.tahoma/ +""" + +import logging +from datetime import timedelta + +from homeassistant.helpers.entity import Entity +from homeassistant.components.sensor import ENTITY_ID_FORMAT +from homeassistant.components.tahoma import ( + DOMAIN as TAHOMA_DOMAIN, TahomaDevice) + +DEPENDENCIES = ['tahoma'] + +_LOGGER = logging.getLogger(__name__) + +SCAN_INTERVAL = timedelta(seconds=10) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up Tahoma controller devices.""" + controller = hass.data[TAHOMA_DOMAIN]['controller'] + devices = [] + for device in hass.data[TAHOMA_DOMAIN]['devices']['sensor']: + devices.append(TahomaSensor(device, controller)) + add_devices(devices, True) + + +class TahomaSensor(TahomaDevice, Entity): + """Representation of a Tahoma Sensor.""" + + def __init__(self, tahoma_device, controller): + """Initialize the sensor.""" + self.current_value = None + super().__init__(tahoma_device, controller) + self.entity_id = ENTITY_ID_FORMAT.format(self.unique_id) + + @property + def state(self): + """Return the name of the sensor.""" + return self.current_value + + @property + def unit_of_measurement(self): + """Return the unit of measurement of this entity, if any.""" + if self.tahoma_device.type == 'Temperature Sensor': + return None + elif self.tahoma_device.type == 'io:LightIOSystemSensor': + return 'lux' + elif self.tahoma_device.type == 'Humidity Sensor': + return '%' + + def update(self): + """Update the state.""" + self.controller.get_states([self.tahoma_device]) + if self.tahoma_device.type == 'io:LightIOSystemSensor': + self.current_value = self.tahoma_device.active_states[ + 'core:LuminanceState'] diff --git a/homeassistant/components/tahoma.py b/homeassistant/components/tahoma.py new file mode 100644 index 00000000000..129c6506ac1 --- /dev/null +++ b/homeassistant/components/tahoma.py @@ -0,0 +1,120 @@ +""" +Support for Tahoma devices. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/tahoma/ +""" +from collections import defaultdict +import logging +import voluptuous as vol +from requests.exceptions import RequestException + +from homeassistant.const import CONF_USERNAME, CONF_PASSWORD, CONF_EXCLUDE +from homeassistant.helpers import discovery +from homeassistant.helpers import config_validation as cv +from homeassistant.helpers.entity import Entity +from homeassistant.util import (slugify) + +REQUIREMENTS = ['tahoma-api==0.0.10'] + +_LOGGER = logging.getLogger(__name__) + +DOMAIN = 'tahoma' + +TAHOMA_ID_FORMAT = '{}_{}' + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Required(CONF_USERNAME): cv.string, + vol.Required(CONF_PASSWORD): cv.string, + vol.Optional(CONF_EXCLUDE, default=[]): + vol.All(cv.ensure_list, [cv.string]), + }), +}, extra=vol.ALLOW_EXTRA) + +TAHOMA_COMPONENTS = [ + 'sensor', 'cover' +] + + +def setup(hass, config): + """Activate Tahoma component.""" + from tahoma_api import TahomaApi + + conf = config[DOMAIN] + username = conf.get(CONF_USERNAME) + password = conf.get(CONF_PASSWORD) + exclude = conf.get(CONF_EXCLUDE) + try: + api = TahomaApi(username, password) + except RequestException: + _LOGGER.exception("Error communicating with Tahoma API") + return False + + try: + api.get_setup() + devices = api.get_devices() + except RequestException: + _LOGGER.exception("Cannot fetch informations from Tahoma API") + return False + + hass.data[DOMAIN] = { + 'controller': api, + 'devices': defaultdict(list) + } + + for device in devices: + _device = api.get_device(device) + if all(ext not in _device.type for ext in exclude): + device_type = map_tahoma_device(_device) + if device_type is None: + continue + hass.data[DOMAIN]['devices'][device_type].append(_device) + + for component in TAHOMA_COMPONENTS: + discovery.load_platform(hass, component, DOMAIN, {}, config) + + return True + + +def map_tahoma_device(tahoma_device): + """Map tahoma classes to Home Assistant types.""" + if tahoma_device.type.lower().find("shutter") != -1: + return 'cover' + elif tahoma_device.type == 'io:LightIOSystemSensor': + return 'sensor' + return None + + +class TahomaDevice(Entity): + """Representation of a Tahoma device entity.""" + + def __init__(self, tahoma_device, controller): + """Initialize the device.""" + self.tahoma_device = tahoma_device + self.controller = controller + self._unique_id = TAHOMA_ID_FORMAT.format( + slugify(tahoma_device.label), slugify(tahoma_device.url)) + self._name = self.tahoma_device.label + + @property + def unique_id(self): + """Return the unique ID for this cover.""" + return self._unique_id + + @property + def name(self): + """Return the name of the device.""" + return self._name + + @property + def device_state_attributes(self): + """Return the state attributes of the device.""" + return {'tahoma_device_id': self.tahoma_device.url} + + def apply_action(self, cmd_name, *args): + """Apply Action to Device.""" + from tahoma_api import Action + action = Action(self.tahoma_device.url) + action.add_command(cmd_name, *args) + self.controller.apply_actions('', [action]) diff --git a/requirements_all.txt b/requirements_all.txt index f1450339058..520848166d0 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1044,6 +1044,9 @@ steamodd==4.21 # homeassistant.components.camera.onvif suds-py3==1.3.3.0 +# homeassistant.components.tahoma +tahoma-api==0.0.10 + # homeassistant.components.sensor.tank_utility tank_utility==1.4.0