Skip to content

Commit

Permalink
Tado: add full list of devices (home-assistant#44475)
Browse files Browse the repository at this point in the history
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
  • Loading branch information
Noltari committed Dec 27, 2020
1 parent 51b8833 commit 6d043f2
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 141 deletions.
17 changes: 4 additions & 13 deletions homeassistant/components/tado/__init__.py
Expand Up @@ -30,7 +30,7 @@
_LOGGER = logging.getLogger(__name__)


TADO_COMPONENTS = ["sensor", "climate", "water_heater"]
TADO_COMPONENTS = ["binary_sensor", "sensor", "climate", "water_heater"]

MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=10)
SCAN_INTERVAL = timedelta(seconds=15)
Expand Down Expand Up @@ -174,7 +174,6 @@ def __init__(self, hass, username, password, fallback):
self.devices = None
self.data = {
"zone": {},
"device": {},
}

@property
Expand All @@ -188,30 +187,22 @@ def setup(self):
self.tado.setDebugging(True)
# Load zones and devices
self.zones = self.tado.getZones()
self.devices = self.tado.getMe()["homes"]
self.device_id = self.devices[0]["id"]
self.devices = self.tado.getDevices()
self.device_id = self.tado.getMe()["homes"][0]["id"]

@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
"""Update the registered zones."""
for zone in self.zones:
self.update_sensor("zone", zone["id"])
for device in self.devices:
self.update_sensor("device", device["id"])
self.devices = self.tado.getDevices()

def update_sensor(self, sensor_type, sensor):
"""Update the internal data from Tado."""
_LOGGER.debug("Updating %s %s", sensor_type, sensor)
try:
if sensor_type == "zone":
data = self.tado.getZoneState(sensor)
elif sensor_type == "device":
devices_data = self.tado.getDevices()
if not devices_data:
_LOGGER.info("There are no devices to setup on this tado account")
return

data = devices_data[0]
else:
_LOGGER.debug("Unknown sensor: %s", sensor_type)
return
Expand Down
127 changes: 127 additions & 0 deletions homeassistant/components/tado/binary_sensor.py
@@ -0,0 +1,127 @@
"""Support for Tado sensors for each zone."""
import logging

from homeassistant.components.binary_sensor import (
DEVICE_CLASS_BATTERY,
DEVICE_CLASS_CONNECTIVITY,
BinarySensorEntity,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect

from .const import DATA, DOMAIN, SIGNAL_TADO_UPDATE_RECEIVED, TYPE_BATTERY, TYPE_POWER
from .entity import TadoDeviceEntity

_LOGGER = logging.getLogger(__name__)

DEVICE_SENSORS = {
TYPE_BATTERY: [
"battery state",
"connection state",
],
TYPE_POWER: [
"connection state",
],
}


async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities
):
"""Set up the Tado sensor platform."""

tado = hass.data[DOMAIN][entry.entry_id][DATA]
devices = tado.devices
entities = []

# Create device sensors
for device in devices:
if "batteryState" in device:
device_type = TYPE_BATTERY
else:
device_type = TYPE_POWER

entities.extend(
[
TadoDeviceSensor(tado, device, variable)
for variable in DEVICE_SENSORS[device_type]
]
)

if entities:
async_add_entities(entities, True)


class TadoDeviceSensor(TadoDeviceEntity, BinarySensorEntity):
"""Representation of a tado Sensor."""

def __init__(self, tado, device_info, device_variable):
"""Initialize of the Tado Sensor."""
self._tado = tado
super().__init__(device_info)

self.device_variable = device_variable

self._unique_id = f"{device_variable} {self.device_id} {tado.device_id}"

self._state = None

async def async_added_to_hass(self):
"""Register for sensor updates."""

self.async_on_remove(
async_dispatcher_connect(
self.hass,
SIGNAL_TADO_UPDATE_RECEIVED.format(
self._tado.device_id, "device", self.device_id
),
self._async_update_callback,
)
)
self._async_update_device_data()

@property
def unique_id(self):
"""Return the unique id."""
return self._unique_id

@property
def name(self):
"""Return the name of the sensor."""
return f"{self.device_name} {self.device_variable}"

@property
def is_on(self):
"""Return true if sensor is on."""
return self._state

@property
def device_class(self):
"""Return the class of this sensor."""
if self.device_variable == "battery state":
return DEVICE_CLASS_BATTERY
if self.device_variable == "connection state":
return DEVICE_CLASS_CONNECTIVITY
return None

@callback
def _async_update_callback(self):
"""Update and write state."""
self._async_update_device_data()
self.async_write_ha_state()

@callback
def _async_update_device_data(self):
"""Handle update callbacks."""
for device in self._tado.devices:
if device["serialNo"] == self.device_id:
self._device_info = device
break

if self.device_variable == "battery state":
self._state = self._device_info["batteryState"] == "LOW"
elif self.device_variable == "connection state":
self._state = self._device_info.get("connectionState", {}).get(
"value", False
)
10 changes: 3 additions & 7 deletions homeassistant/components/tado/climate.py
Expand Up @@ -89,15 +89,13 @@ def _generate_entities(tado):
entities = []
for zone in tado.zones:
if zone["type"] in [TYPE_HEATING, TYPE_AIR_CONDITIONING]:
entity = create_climate_entity(
tado, zone["name"], zone["id"], zone["devices"][0]
)
entity = create_climate_entity(tado, zone["name"], zone["id"])
if entity:
entities.append(entity)
return entities


def create_climate_entity(tado, name: str, zone_id: int, zone: dict):
def create_climate_entity(tado, name: str, zone_id: int):
"""Create a Tado climate entity."""
capabilities = tado.get_capabilities(zone_id)
_LOGGER.debug("Capabilities for zone %s: %s", zone_id, capabilities)
Expand Down Expand Up @@ -180,7 +178,6 @@ def create_climate_entity(tado, name: str, zone_id: int, zone: dict):
supported_hvac_modes,
supported_fan_modes,
support_flags,
zone,
)
return entity

Expand All @@ -203,11 +200,10 @@ def __init__(
supported_hvac_modes,
supported_fan_modes,
support_flags,
device_info,
):
"""Initialize of Tado climate entity."""
self._tado = tado
super().__init__(zone_name, device_info, tado.device_id, zone_id)
super().__init__(zone_name, tado.device_id, zone_id)

self.zone_id = zone_id
self.zone_type = zone_type
Expand Down
5 changes: 4 additions & 1 deletion homeassistant/components/tado/const.py
Expand Up @@ -53,6 +53,9 @@
TYPE_HEATING = "HEATING"
TYPE_HOT_WATER = "HOT_WATER"

TYPE_BATTERY = "BATTERY"
TYPE_POWER = "POWER"

# Base modes
CONST_MODE_OFF = "OFF"
CONST_MODE_SMART_SCHEDULE = "SMART_SCHEDULE" # Use the schedule
Expand Down Expand Up @@ -144,6 +147,6 @@

DEFAULT_NAME = "Tado"

TADO_BRIDGE = "Tado Bridge"
TADO_ZONE = "Zone"

UPDATE_LISTENER = "update_listener"
43 changes: 34 additions & 9 deletions homeassistant/components/tado/entity.py
@@ -1,17 +1,44 @@
"""Base class for August entity."""
"""Base class for Tado entity."""
from homeassistant.helpers.entity import Entity

from .const import DEFAULT_NAME, DOMAIN
from .const import DEFAULT_NAME, DOMAIN, TADO_ZONE


class TadoDeviceEntity(Entity):
"""Base implementation for Tado device."""

def __init__(self, device_info):
"""Initialize a Tado device."""
super().__init__()
self._device_info = device_info
self.device_name = device_info["shortSerialNo"]
self.device_id = device_info["serialNo"]

@property
def device_info(self):
"""Return the device_info of the device."""
return {
"identifiers": {(DOMAIN, self.device_id)},
"name": self.device_name,
"manufacturer": DEFAULT_NAME,
"sw_version": self._device_info["currentFwVersion"],
"model": self._device_info["deviceType"],
"via_device": (DOMAIN, self._device_info["serialNo"]),
}

@property
def should_poll(self):
"""Do not poll."""
return False


class TadoZoneEntity(Entity):
"""Base implementation for tado device."""
"""Base implementation for Tado zone."""

def __init__(self, zone_name, device_info, device_id, zone_id):
"""Initialize an August device."""
def __init__(self, zone_name, device_id, zone_id):
"""Initialize a Tado zone."""
super().__init__()
self._device_zone_id = f"{device_id}_{zone_id}"
self._device_info = device_info
self.zone_name = zone_name

@property
Expand All @@ -21,9 +48,7 @@ def device_info(self):
"identifiers": {(DOMAIN, self._device_zone_id)},
"name": self.zone_name,
"manufacturer": DEFAULT_NAME,
"sw_version": self._device_info["currentFwVersion"],
"model": self._device_info["deviceType"],
"via_device": (DOMAIN, self._device_info["serialNo"]),
"model": TADO_ZONE,
}

@property
Expand Down

0 comments on commit 6d043f2

Please sign in to comment.