Skip to content

Commit

Permalink
Revert Tahoma removal (#29840)
Browse files Browse the repository at this point in the history
* Revert "Remove Tahoma component #29744 (#29745)"

This reverts commit df74272.

* Revert "Cleanup removed component (#29788)"

This reverts commit 3a28361.
  • Loading branch information
balloob committed Dec 12, 2019
1 parent 7bd98d1 commit b9eb831
Show file tree
Hide file tree
Showing 10 changed files with 757 additions and 0 deletions.
1 change: 1 addition & 0 deletions .coveragerc
Expand Up @@ -676,6 +676,7 @@ omit =
homeassistant/components/systemmonitor/sensor.py
homeassistant/components/tado/*
homeassistant/components/tado/device_tracker.py
homeassistant/components/tahoma/*
homeassistant/components/tank_utility/sensor.py
homeassistant/components/tapsaff/binary_sensor.py
homeassistant/components/tautulli/sensor.py
Expand Down
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Expand Up @@ -318,6 +318,7 @@ homeassistant/components/syncthru/* @nielstron
homeassistant/components/synology_srm/* @aerialls
homeassistant/components/syslog/* @fabaff
homeassistant/components/tado/* @michaelarnauts
homeassistant/components/tahoma/* @philklei
homeassistant/components/tautulli/* @ludeeus
homeassistant/components/tellduslive/* @fredrike
homeassistant/components/template/* @PhracturedBlue
Expand Down
140 changes: 140 additions & 0 deletions homeassistant/components/tahoma/__init__.py
@@ -0,0 +1,140 @@
"""Support for Tahoma devices."""
from collections import defaultdict
import logging

from requests.exceptions import RequestException
from tahoma_api import Action, TahomaApi
import voluptuous as vol

from homeassistant.const import CONF_EXCLUDE, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import config_validation as cv, discovery
from homeassistant.helpers.entity import Entity

_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 = ["scene", "sensor", "cover", "switch", "binary_sensor"]

TAHOMA_TYPES = {
"io:ExteriorVenetianBlindIOComponent": "cover",
"io:HorizontalAwningIOComponent": "cover",
"io:LightIOSystemSensor": "sensor",
"io:OnOffIOComponent": "switch",
"io:OnOffLightIOComponent": "switch",
"io:RollerShutterGenericIOComponent": "cover",
"io:RollerShutterUnoIOComponent": "cover",
"io:RollerShutterVeluxIOComponent": "cover",
"io:RollerShutterWithLowSpeedManagementIOComponent": "cover",
"io:SomfyBasicContactIOSystemSensor": "sensor",
"io:SomfyContactIOSystemSensor": "sensor",
"io:VerticalExteriorAwningIOComponent": "cover",
"io:VerticalInteriorBlindVeluxIOComponent": "cover",
"io:WindowOpenerVeluxIOComponent": "cover",
"io:GarageOpenerIOComponent": "cover",
"io:DiscreteGarageOpenerIOComponent": "cover",
"rtds:RTDSContactSensor": "sensor",
"rtds:RTDSMotionSensor": "sensor",
"rtds:RTDSSmokeSensor": "smoke",
"rts:BlindRTSComponent": "cover",
"rts:CurtainRTSComponent": "cover",
"rts:DualCurtainRTSComponent": "cover",
"rts:ExteriorVenetianBlindRTSComponent": "cover",
"rts:GarageDoor4TRTSComponent": "switch",
"rts:RollerShutterRTSComponent": "cover",
"rts:VenetianBlindRTSComponent": "cover",
}


def setup(hass, config):
"""Activate Tahoma component."""

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 when trying to log in to the Tahoma API")
return False

try:
api.get_setup()
devices = api.get_devices()
scenes = api.get_action_groups()
except RequestException:
_LOGGER.exception("Error when getting devices from the Tahoma API")
return False

hass.data[DOMAIN] = {"controller": api, "devices": defaultdict(list), "scenes": []}

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:
_LOGGER.warning(
"Unsupported type %s for Tahoma device %s",
_device.type,
_device.label,
)
continue
hass.data[DOMAIN]["devices"][device_type].append(_device)

for scene in scenes:
hass.data[DOMAIN]["scenes"].append(scene)

for component in TAHOMA_COMPONENTS:
discovery.load_platform(hass, component, DOMAIN, {}, config)

return True


def map_tahoma_device(tahoma_device):
"""Map Tahoma device types to Home Assistant components."""
return TAHOMA_TYPES.get(tahoma_device.type)


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._name = self.tahoma_device.label

@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."""

action = Action(self.tahoma_device.url)
action.add_command(cmd_name, *args)
self.controller.apply_actions("HomeAssistant", [action])
95 changes: 95 additions & 0 deletions homeassistant/components/tahoma/binary_sensor.py
@@ -0,0 +1,95 @@
"""Support for Tahoma binary sensors."""
from datetime import timedelta
import logging

from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.const import ATTR_BATTERY_LEVEL, STATE_OFF, STATE_ON

from . import DOMAIN as TAHOMA_DOMAIN, TahomaDevice

_LOGGER = logging.getLogger(__name__)

SCAN_INTERVAL = timedelta(seconds=120)


def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up Tahoma controller devices."""
_LOGGER.debug("Setup Tahoma Binary sensor platform")
controller = hass.data[TAHOMA_DOMAIN]["controller"]
devices = []
for device in hass.data[TAHOMA_DOMAIN]["devices"]["smoke"]:
devices.append(TahomaBinarySensor(device, controller))
add_entities(devices, True)


class TahomaBinarySensor(TahomaDevice, BinarySensorDevice):
"""Representation of a Tahoma Binary Sensor."""

def __init__(self, tahoma_device, controller):
"""Initialize the sensor."""
super().__init__(tahoma_device, controller)

self._state = None
self._icon = None
self._battery = None
self._available = False

@property
def is_on(self):
"""Return the state of the sensor."""
return bool(self._state == STATE_ON)

@property
def device_class(self):
"""Return the class of the device."""
if self.tahoma_device.type == "rtds:RTDSSmokeSensor":
return "smoke"
return None

@property
def icon(self):
"""Icon for device by its type."""
return self._icon

@property
def device_state_attributes(self):
"""Return the device state attributes."""
attr = {}
super_attr = super().device_state_attributes
if super_attr is not None:
attr.update(super_attr)

if self._battery is not None:
attr[ATTR_BATTERY_LEVEL] = self._battery
return attr

@property
def available(self):
"""Return True if entity is available."""
return self._available

def update(self):
"""Update the state."""
self.controller.get_states([self.tahoma_device])
if self.tahoma_device.type == "rtds:RTDSSmokeSensor":
if self.tahoma_device.active_states["core:SmokeState"] == "notDetected":
self._state = STATE_OFF
else:
self._state = STATE_ON

if "core:SensorDefectState" in self.tahoma_device.active_states:
# 'lowBattery' for low battery warning. 'dead' for not available.
self._battery = self.tahoma_device.active_states["core:SensorDefectState"]
self._available = bool(self._battery != "dead")
else:
self._battery = None
self._available = True

if self._state == STATE_ON:
self._icon = "mdi:fire"
elif self._battery == "lowBattery":
self._icon = "mdi:battery-alert"
else:
self._icon = None

_LOGGER.debug("Update %s, state: %s", self._name, self._state)

0 comments on commit b9eb831

Please sign in to comment.