Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert Tahoma removal #29840

Merged
merged 2 commits into from Dec 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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)