2019-02-13 20:21:14 +00:00
|
|
|
"""Support for Tado sensors for each zone."""
|
2017-03-22 12:18:13 +00:00
|
|
|
import logging
|
|
|
|
|
2018-05-14 11:05:52 +00:00
|
|
|
from homeassistant.const import ATTR_ID, ATTR_NAME, TEMP_CELSIUS
|
2017-03-22 12:18:13 +00:00
|
|
|
from homeassistant.helpers.entity import Entity
|
|
|
|
|
2019-03-21 05:56:46 +00:00
|
|
|
from . import DATA_TADO
|
|
|
|
|
2017-03-22 12:18:13 +00:00
|
|
|
_LOGGER = logging.getLogger(__name__)
|
2017-04-24 03:41:09 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
ATTR_DATA_ID = "data_id"
|
|
|
|
ATTR_DEVICE = "device"
|
|
|
|
ATTR_ZONE = "zone"
|
2017-04-24 03:41:09 +00:00
|
|
|
|
2019-08-12 04:02:16 +00:00
|
|
|
CLIMATE_HEAT_SENSOR_TYPES = [
|
2019-07-31 19:25:30 +00:00
|
|
|
"temperature",
|
|
|
|
"humidity",
|
|
|
|
"power",
|
|
|
|
"link",
|
|
|
|
"heating",
|
|
|
|
"tado mode",
|
|
|
|
"overlay",
|
2019-11-25 08:13:59 +00:00
|
|
|
"early start",
|
2019-07-31 19:25:30 +00:00
|
|
|
]
|
2018-01-11 09:49:41 +00:00
|
|
|
|
2019-08-12 04:02:16 +00:00
|
|
|
CLIMATE_COOL_SENSOR_TYPES = [
|
|
|
|
"temperature",
|
|
|
|
"humidity",
|
|
|
|
"power",
|
|
|
|
"link",
|
|
|
|
"ac",
|
|
|
|
"tado mode",
|
|
|
|
"overlay",
|
|
|
|
]
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
HOT_WATER_SENSOR_TYPES = ["power", "link", "tado mode", "overlay"]
|
2017-03-22 12:18:13 +00:00
|
|
|
|
|
|
|
|
2018-08-24 14:37:30 +00:00
|
|
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
2017-04-24 03:41:09 +00:00
|
|
|
"""Set up the sensor platform."""
|
2017-03-22 12:18:13 +00:00
|
|
|
tado = hass.data[DATA_TADO]
|
|
|
|
|
|
|
|
try:
|
|
|
|
zones = tado.get_zones()
|
|
|
|
except RuntimeError:
|
|
|
|
_LOGGER.error("Unable to get zone info from mytado")
|
2017-07-06 06:30:01 +00:00
|
|
|
return
|
2017-03-22 12:18:13 +00:00
|
|
|
|
|
|
|
sensor_items = []
|
|
|
|
for zone in zones:
|
2019-07-31 19:25:30 +00:00
|
|
|
if zone["type"] == "HEATING":
|
2019-08-12 04:02:16 +00:00
|
|
|
for variable in CLIMATE_HEAT_SENSOR_TYPES:
|
2019-07-31 19:25:30 +00:00
|
|
|
sensor_items.append(
|
|
|
|
create_zone_sensor(tado, zone, zone["name"], zone["id"], variable)
|
|
|
|
)
|
|
|
|
elif zone["type"] == "HOT_WATER":
|
2018-01-11 09:49:41 +00:00
|
|
|
for variable in HOT_WATER_SENSOR_TYPES:
|
2019-07-31 19:25:30 +00:00
|
|
|
sensor_items.append(
|
|
|
|
create_zone_sensor(tado, zone, zone["name"], zone["id"], variable)
|
|
|
|
)
|
2019-08-12 04:02:16 +00:00
|
|
|
elif zone["type"] == "AIR_CONDITIONING":
|
|
|
|
for variable in CLIMATE_COOL_SENSOR_TYPES:
|
|
|
|
sensor_items.append(
|
|
|
|
create_zone_sensor(tado, zone, zone["name"], zone["id"], variable)
|
|
|
|
)
|
2017-03-22 12:18:13 +00:00
|
|
|
|
|
|
|
me_data = tado.get_me()
|
2019-07-31 19:25:30 +00:00
|
|
|
sensor_items.append(
|
|
|
|
create_device_sensor(
|
|
|
|
tado,
|
|
|
|
me_data,
|
|
|
|
me_data["homes"][0]["name"],
|
|
|
|
me_data["homes"][0]["id"],
|
|
|
|
"tado bridge status",
|
|
|
|
)
|
|
|
|
)
|
2017-03-22 12:18:13 +00:00
|
|
|
|
2017-04-24 03:41:09 +00:00
|
|
|
if sensor_items:
|
2018-08-24 14:37:30 +00:00
|
|
|
add_entities(sensor_items, True)
|
2017-03-22 12:18:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
def create_zone_sensor(tado, zone, name, zone_id, variable):
|
|
|
|
"""Create a zone sensor."""
|
2019-09-03 19:12:51 +00:00
|
|
|
data_id = f"zone {name} {zone_id}"
|
2017-03-22 12:18:13 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
tado.add_sensor(
|
|
|
|
data_id,
|
|
|
|
{ATTR_ZONE: zone, ATTR_NAME: name, ATTR_ID: zone_id, ATTR_DATA_ID: data_id},
|
|
|
|
)
|
2017-03-22 12:18:13 +00:00
|
|
|
|
|
|
|
return TadoSensor(tado, name, zone_id, variable, data_id)
|
|
|
|
|
|
|
|
|
|
|
|
def create_device_sensor(tado, device, name, device_id, variable):
|
|
|
|
"""Create a device sensor."""
|
2019-09-03 19:12:51 +00:00
|
|
|
data_id = f"device {name} {device_id}"
|
2019-07-31 19:25:30 +00:00
|
|
|
|
|
|
|
tado.add_sensor(
|
|
|
|
data_id,
|
|
|
|
{
|
|
|
|
ATTR_DEVICE: device,
|
|
|
|
ATTR_NAME: name,
|
|
|
|
ATTR_ID: device_id,
|
|
|
|
ATTR_DATA_ID: data_id,
|
|
|
|
},
|
|
|
|
)
|
2017-03-22 12:18:13 +00:00
|
|
|
|
|
|
|
return TadoSensor(tado, name, device_id, variable, data_id)
|
|
|
|
|
|
|
|
|
|
|
|
class TadoSensor(Entity):
|
|
|
|
"""Representation of a tado Sensor."""
|
|
|
|
|
|
|
|
def __init__(self, store, zone_name, zone_id, zone_variable, data_id):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Initialize of the Tado Sensor."""
|
2017-03-22 12:18:13 +00:00
|
|
|
self._store = store
|
|
|
|
|
|
|
|
self.zone_name = zone_name
|
|
|
|
self.zone_id = zone_id
|
|
|
|
self.zone_variable = zone_variable
|
|
|
|
|
2019-09-03 19:12:51 +00:00
|
|
|
self._unique_id = f"{zone_variable} {zone_id}"
|
2017-03-22 12:18:13 +00:00
|
|
|
self._data_id = data_id
|
|
|
|
|
|
|
|
self._state = None
|
|
|
|
self._state_attributes = None
|
|
|
|
|
|
|
|
@property
|
|
|
|
def unique_id(self):
|
|
|
|
"""Return the unique id."""
|
|
|
|
return self._unique_id
|
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
"""Return the name of the sensor."""
|
2019-09-03 19:12:51 +00:00
|
|
|
return f"{self.zone_name} {self.zone_variable}"
|
2017-03-22 12:18:13 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def state(self):
|
|
|
|
"""Return the state of the sensor."""
|
|
|
|
return self._state
|
|
|
|
|
|
|
|
@property
|
|
|
|
def device_state_attributes(self):
|
|
|
|
"""Return the state attributes."""
|
|
|
|
return self._state_attributes
|
|
|
|
|
|
|
|
@property
|
|
|
|
def unit_of_measurement(self):
|
|
|
|
"""Return the unit of measurement."""
|
|
|
|
if self.zone_variable == "temperature":
|
|
|
|
return self.hass.config.units.temperature_unit
|
2018-07-23 08:16:05 +00:00
|
|
|
if self.zone_variable == "humidity":
|
2019-07-31 19:25:30 +00:00
|
|
|
return "%"
|
2018-07-23 08:16:05 +00:00
|
|
|
if self.zone_variable == "heating":
|
2019-07-31 19:25:30 +00:00
|
|
|
return "%"
|
2019-08-12 04:02:16 +00:00
|
|
|
if self.zone_variable == "ac":
|
|
|
|
return ""
|
2017-03-22 12:18:13 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def icon(self):
|
|
|
|
"""Icon for the sensor."""
|
|
|
|
if self.zone_variable == "temperature":
|
2019-07-31 19:25:30 +00:00
|
|
|
return "mdi:thermometer"
|
2018-07-23 08:16:05 +00:00
|
|
|
if self.zone_variable == "humidity":
|
2019-07-31 19:25:30 +00:00
|
|
|
return "mdi:water-percent"
|
2017-03-22 12:18:13 +00:00
|
|
|
|
|
|
|
def update(self):
|
|
|
|
"""Update method called when should_poll is true."""
|
|
|
|
self._store.update()
|
|
|
|
|
|
|
|
data = self._store.get_data(self._data_id)
|
|
|
|
|
|
|
|
if data is None:
|
2018-01-27 19:58:27 +00:00
|
|
|
_LOGGER.debug("Received no data for zone %s", self.zone_name)
|
2017-03-22 12:18:13 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
unit = TEMP_CELSIUS
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
if self.zone_variable == "temperature":
|
|
|
|
if "sensorDataPoints" in data:
|
|
|
|
sensor_data = data["sensorDataPoints"]
|
|
|
|
temperature = float(sensor_data["insideTemperature"]["celsius"])
|
2017-03-22 12:18:13 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
self._state = self.hass.config.units.temperature(temperature, unit)
|
2017-03-22 12:18:13 +00:00
|
|
|
self._state_attributes = {
|
2019-07-31 19:25:30 +00:00
|
|
|
"time": sensor_data["insideTemperature"]["timestamp"],
|
|
|
|
"setting": 0, # setting is used in climate device
|
2017-03-22 12:18:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# temperature setting will not exist when device is off
|
2019-07-31 19:25:30 +00:00
|
|
|
if (
|
|
|
|
"temperature" in data["setting"]
|
|
|
|
and data["setting"]["temperature"] is not None
|
|
|
|
):
|
|
|
|
temperature = float(data["setting"]["temperature"]["celsius"])
|
|
|
|
|
|
|
|
self._state_attributes[
|
|
|
|
"setting"
|
|
|
|
] = self.hass.config.units.temperature(temperature, unit)
|
|
|
|
|
|
|
|
elif self.zone_variable == "humidity":
|
|
|
|
if "sensorDataPoints" in data:
|
|
|
|
sensor_data = data["sensorDataPoints"]
|
|
|
|
self._state = float(sensor_data["humidity"]["percentage"])
|
|
|
|
self._state_attributes = {"time": sensor_data["humidity"]["timestamp"]}
|
|
|
|
|
|
|
|
elif self.zone_variable == "power":
|
|
|
|
if "setting" in data:
|
|
|
|
self._state = data["setting"]["power"]
|
|
|
|
|
|
|
|
elif self.zone_variable == "link":
|
|
|
|
if "link" in data:
|
|
|
|
self._state = data["link"]["state"]
|
|
|
|
|
|
|
|
elif self.zone_variable == "heating":
|
|
|
|
if "activityDataPoints" in data:
|
|
|
|
activity_data = data["activityDataPoints"]
|
2019-08-12 04:02:16 +00:00
|
|
|
|
|
|
|
if (
|
|
|
|
"heatingPower" in activity_data
|
|
|
|
and activity_data["heatingPower"] is not None
|
|
|
|
):
|
|
|
|
self._state = float(activity_data["heatingPower"]["percentage"])
|
|
|
|
self._state_attributes = {
|
|
|
|
"time": activity_data["heatingPower"]["timestamp"]
|
|
|
|
}
|
|
|
|
|
|
|
|
elif self.zone_variable == "ac":
|
|
|
|
if "activityDataPoints" in data:
|
|
|
|
activity_data = data["activityDataPoints"]
|
|
|
|
|
|
|
|
if "acPower" in activity_data and activity_data["acPower"] is not None:
|
|
|
|
self._state = activity_data["acPower"]["value"]
|
|
|
|
self._state_attributes = {
|
|
|
|
"time": activity_data["acPower"]["timestamp"]
|
|
|
|
}
|
2017-03-22 12:18:13 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
elif self.zone_variable == "tado bridge status":
|
|
|
|
if "connectionState" in data:
|
|
|
|
self._state = data["connectionState"]["value"]
|
2017-03-22 12:18:13 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
elif self.zone_variable == "tado mode":
|
|
|
|
if "tadoMode" in data:
|
|
|
|
self._state = data["tadoMode"]
|
2017-03-22 12:18:13 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
elif self.zone_variable == "overlay":
|
|
|
|
if "overlay" in data and data["overlay"] is not None:
|
2017-03-22 12:18:13 +00:00
|
|
|
self._state = True
|
|
|
|
self._state_attributes = {
|
2019-07-31 19:25:30 +00:00
|
|
|
"termination": data["overlay"]["termination"]["type"]
|
2017-03-22 12:18:13 +00:00
|
|
|
}
|
|
|
|
else:
|
|
|
|
self._state = False
|
|
|
|
self._state_attributes = {}
|
2019-11-25 08:13:59 +00:00
|
|
|
|
|
|
|
elif self.zone_variable == "early start":
|
|
|
|
if "preparation" in data and data["preparation"] is not None:
|
|
|
|
self._state = True
|
|
|
|
else:
|
|
|
|
self._state = False
|