mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Telldus Live: (#4645)
- Implemented support for covers and dimmable lights. - Removed global object, use hass.data. - Disabled polling via update. - Inherit from common TelldusLiveEntity device. - Configurable polling interval - Use https API endpoint - Use tellduslive package
This commit is contained in:
parent
04aa4e898a
commit
2a7fa5afc3
46
homeassistant/components/cover/tellduslive.py
Normal file
46
homeassistant/components/cover/tellduslive.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
"""
|
||||||
|
Support for Tellstick covers using Tellstick Net.
|
||||||
|
|
||||||
|
This platform uses the Telldus Live online service.
|
||||||
|
|
||||||
|
For more details about this platform, please refer to the documentation at
|
||||||
|
https://home-assistant.io/components/cover.tellduslive/
|
||||||
|
|
||||||
|
"""
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from homeassistant.components.cover import CoverDevice
|
||||||
|
from homeassistant.components.tellduslive import TelldusLiveEntity
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
|
"""Setup covers."""
|
||||||
|
if discovery_info is None:
|
||||||
|
return
|
||||||
|
add_devices(TelldusLiveCover(hass, cover) for cover in discovery_info)
|
||||||
|
|
||||||
|
|
||||||
|
class TelldusLiveCover(TelldusLiveEntity, CoverDevice):
|
||||||
|
"""Representation of a cover."""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_closed(self):
|
||||||
|
"""Return the current position of the cover."""
|
||||||
|
return self.device.is_down
|
||||||
|
|
||||||
|
def close_cover(self, **kwargs):
|
||||||
|
"""Close the cover."""
|
||||||
|
self.device.down()
|
||||||
|
self.changed()
|
||||||
|
|
||||||
|
def open_cover(self, **kwargs):
|
||||||
|
"""Open the cover."""
|
||||||
|
self.device.up()
|
||||||
|
self.changed()
|
||||||
|
|
||||||
|
def stop_cover(self, **kwargs):
|
||||||
|
"""Stop the cover."""
|
||||||
|
self.device.stop()
|
||||||
|
self.changed()
|
59
homeassistant/components/light/tellduslive.py
Normal file
59
homeassistant/components/light/tellduslive.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
"""
|
||||||
|
Support for Tellstick switches using Tellstick Net.
|
||||||
|
|
||||||
|
This platform uses the Telldus Live online service.
|
||||||
|
|
||||||
|
For more details about this platform, please refer to the documentation at
|
||||||
|
https://home-assistant.io/components/light.tellduslive/
|
||||||
|
|
||||||
|
"""
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from homeassistant.components.light import (
|
||||||
|
ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, Light)
|
||||||
|
from homeassistant.components.tellduslive import TelldusLiveEntity
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
|
"""Setup lights."""
|
||||||
|
if discovery_info is None:
|
||||||
|
return
|
||||||
|
add_devices(TelldusLiveLight(hass, light) for light in discovery_info)
|
||||||
|
|
||||||
|
|
||||||
|
class TelldusLiveLight(TelldusLiveEntity, Light):
|
||||||
|
"""Representation of a light."""
|
||||||
|
|
||||||
|
def changed(self):
|
||||||
|
"""A property of the device might have changed."""
|
||||||
|
# pylint: disable=attribute-defined-outside-init
|
||||||
|
self._last_brightness = self.brightness
|
||||||
|
super().changed()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def brightness(self):
|
||||||
|
"""Return the brightness of this light between 0..255."""
|
||||||
|
return self.device.dim_level
|
||||||
|
|
||||||
|
@property
|
||||||
|
def supported_features(self):
|
||||||
|
"""Flag supported features."""
|
||||||
|
return SUPPORT_BRIGHTNESS
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_on(self):
|
||||||
|
"""Return true if light is on."""
|
||||||
|
return self.device.is_on
|
||||||
|
|
||||||
|
def turn_on(self, **kwargs):
|
||||||
|
"""Turn the light on."""
|
||||||
|
brightness = kwargs.get(ATTR_BRIGHTNESS, self._last_brightness)
|
||||||
|
self.device.dim(level=brightness)
|
||||||
|
self.changed()
|
||||||
|
|
||||||
|
def turn_off(self, **kwargs):
|
||||||
|
"""Turn the light off."""
|
||||||
|
self.device.turn_off()
|
||||||
|
self.changed()
|
@ -6,37 +6,32 @@ https://home-assistant.io/components/sensor.tellduslive/
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
from homeassistant.components import tellduslive
|
from homeassistant.components.tellduslive import TelldusLiveEntity
|
||||||
from homeassistant.const import (
|
from homeassistant.const import TEMP_CELSIUS
|
||||||
ATTR_BATTERY_LEVEL, DEVICE_DEFAULT_NAME, TEMP_CELSIUS)
|
|
||||||
from homeassistant.helpers.entity import Entity
|
|
||||||
|
|
||||||
ATTR_LAST_UPDATED = "time_last_updated"
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
SENSOR_TYPE_TEMP = "temp"
|
SENSOR_TYPE_TEMP = 'temp'
|
||||||
SENSOR_TYPE_HUMIDITY = "humidity"
|
SENSOR_TYPE_HUMIDITY = 'humidity'
|
||||||
SENSOR_TYPE_RAINRATE = "rrate"
|
SENSOR_TYPE_RAINRATE = 'rrate'
|
||||||
SENSOR_TYPE_RAINTOTAL = "rtot"
|
SENSOR_TYPE_RAINTOTAL = 'rtot'
|
||||||
SENSOR_TYPE_WINDDIRECTION = "wdir"
|
SENSOR_TYPE_WINDDIRECTION = 'wdir'
|
||||||
SENSOR_TYPE_WINDAVERAGE = "wavg"
|
SENSOR_TYPE_WINDAVERAGE = 'wavg'
|
||||||
SENSOR_TYPE_WINDGUST = "wgust"
|
SENSOR_TYPE_WINDGUST = 'wgust'
|
||||||
SENSOR_TYPE_WATT = "watt"
|
SENSOR_TYPE_WATT = 'watt'
|
||||||
SENSOR_TYPE_LUMINANCE = "lum"
|
SENSOR_TYPE_LUMINANCE = 'lum'
|
||||||
|
|
||||||
SENSOR_TYPES = {
|
SENSOR_TYPES = {
|
||||||
SENSOR_TYPE_TEMP: ['Temperature', TEMP_CELSIUS, "mdi:thermometer"],
|
SENSOR_TYPE_TEMP: ['Temperature', TEMP_CELSIUS, 'mdi:thermometer'],
|
||||||
SENSOR_TYPE_HUMIDITY: ['Humidity', '%', "mdi:water"],
|
SENSOR_TYPE_HUMIDITY: ['Humidity', '%', 'mdi:water'],
|
||||||
SENSOR_TYPE_RAINRATE: ['Rain rate', 'mm', "mdi:water"],
|
SENSOR_TYPE_RAINRATE: ['Rain rate', 'mm', 'mdi:water'],
|
||||||
SENSOR_TYPE_RAINTOTAL: ['Rain total', 'mm', "mdi:water"],
|
SENSOR_TYPE_RAINTOTAL: ['Rain total', 'mm', 'mdi:water'],
|
||||||
SENSOR_TYPE_WINDDIRECTION: ['Wind direction', '', ""],
|
SENSOR_TYPE_WINDDIRECTION: ['Wind direction', '', ''],
|
||||||
SENSOR_TYPE_WINDAVERAGE: ['Wind average', 'm/s', ""],
|
SENSOR_TYPE_WINDAVERAGE: ['Wind average', 'm/s', ''],
|
||||||
SENSOR_TYPE_WINDGUST: ['Wind gust', 'm/s', ""],
|
SENSOR_TYPE_WINDGUST: ['Wind gust', 'm/s', ''],
|
||||||
SENSOR_TYPE_WATT: ['Watt', 'W', ""],
|
SENSOR_TYPE_WATT: ['Watt', 'W', ''],
|
||||||
SENSOR_TYPE_LUMINANCE: ['Luminance', 'lx', ""],
|
SENSOR_TYPE_LUMINANCE: ['Luminance', 'lx', ''],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -44,114 +39,75 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
"""Setup Tellstick sensors."""
|
"""Setup Tellstick sensors."""
|
||||||
if discovery_info is None:
|
if discovery_info is None:
|
||||||
return
|
return
|
||||||
add_devices(TelldusLiveSensor(sensor) for sensor in discovery_info)
|
add_devices(TelldusLiveSensor(hass, sensor) for sensor in discovery_info)
|
||||||
|
|
||||||
|
|
||||||
class TelldusLiveSensor(Entity):
|
class TelldusLiveSensor(TelldusLiveEntity):
|
||||||
"""Representation of a Telldus Live sensor."""
|
"""Representation of a Telldus Live sensor."""
|
||||||
|
|
||||||
def __init__(self, sensor_id):
|
@property
|
||||||
"""Initialize the sensor."""
|
def device_id(self):
|
||||||
self._id = sensor_id
|
"""Return id of the device."""
|
||||||
self.update()
|
return self._id[0]
|
||||||
_LOGGER.debug("created sensor %s", self)
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
"""Update sensor values."""
|
|
||||||
tellduslive.NETWORK.update_sensors()
|
|
||||||
self._sensor = tellduslive.NETWORK.get_sensor(self._id)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _sensor_name(self):
|
def _type(self):
|
||||||
"""Return the name of the sensor."""
|
|
||||||
return self._sensor["name"]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def _sensor_value(self):
|
|
||||||
"""Return the value the sensor."""
|
|
||||||
return self._sensor["data"]["value"]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def _sensor_type(self):
|
|
||||||
"""Return the type of the sensor."""
|
"""Return the type of the sensor."""
|
||||||
return self._sensor["data"]["name"]
|
return self._id[1]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _battery_level(self):
|
def _value(self):
|
||||||
"""Return the battery level of a sensor."""
|
"""Return value of the sensor."""
|
||||||
sensor_battery_level = self._sensor.get("battery")
|
return self.device.value(self._id[1:])
|
||||||
return round(sensor_battery_level * 100 / 255) \
|
|
||||||
if sensor_battery_level else None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def _last_updated(self):
|
|
||||||
"""Return the last update."""
|
|
||||||
sensor_last_updated = self._sensor.get("lastUpdated")
|
|
||||||
return str(datetime.fromtimestamp(sensor_last_updated)) \
|
|
||||||
if sensor_last_updated else None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _value_as_temperature(self):
|
def _value_as_temperature(self):
|
||||||
"""Return the value as temperature."""
|
"""Return the value as temperature."""
|
||||||
return round(float(self._sensor_value), 1)
|
return round(float(self._value), 1)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _value_as_luminance(self):
|
def _value_as_luminance(self):
|
||||||
"""Return the value as luminance."""
|
"""Return the value as luminance."""
|
||||||
return round(float(self._sensor_value), 1)
|
return round(float(self._value), 1)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _value_as_humidity(self):
|
def _value_as_humidity(self):
|
||||||
"""Return the value as humidity."""
|
"""Return the value as humidity."""
|
||||||
return int(round(float(self._sensor_value)))
|
return int(round(float(self._value)))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of the sensor."""
|
"""Return the name of the sensor."""
|
||||||
return "{} {}".format(self._sensor_name or DEVICE_DEFAULT_NAME,
|
return '{} {}'.format(
|
||||||
self.quantity_name or "")
|
super().name,
|
||||||
|
self.quantity_name or '')
|
||||||
@property
|
|
||||||
def available(self):
|
|
||||||
"""Return true if the sensor is available."""
|
|
||||||
return not self._sensor.get("offline", False)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self):
|
||||||
"""Return the state of the sensor."""
|
"""Return the state of the sensor."""
|
||||||
if self._sensor_type == SENSOR_TYPE_TEMP:
|
if self._type == SENSOR_TYPE_TEMP:
|
||||||
return self._value_as_temperature
|
return self._value_as_temperature
|
||||||
elif self._sensor_type == SENSOR_TYPE_HUMIDITY:
|
elif self._type == SENSOR_TYPE_HUMIDITY:
|
||||||
return self._value_as_humidity
|
return self._value_as_humidity
|
||||||
elif self._sensor_type == SENSOR_TYPE_LUMINANCE:
|
elif self._type == SENSOR_TYPE_LUMINANCE:
|
||||||
return self._value_as_luminance
|
return self._value_as_luminance
|
||||||
else:
|
else:
|
||||||
return self._sensor_value
|
return self._value
|
||||||
|
|
||||||
@property
|
|
||||||
def device_state_attributes(self):
|
|
||||||
"""Return the state attributes."""
|
|
||||||
attrs = {}
|
|
||||||
if self._battery_level is not None:
|
|
||||||
attrs[ATTR_BATTERY_LEVEL] = self._battery_level
|
|
||||||
if self._last_updated is not None:
|
|
||||||
attrs[ATTR_LAST_UPDATED] = self._last_updated
|
|
||||||
return attrs
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def quantity_name(self):
|
def quantity_name(self):
|
||||||
"""Name of quantity."""
|
"""Name of quantity."""
|
||||||
return SENSOR_TYPES[self._sensor_type][0] \
|
return SENSOR_TYPES[self._type][0] \
|
||||||
if self._sensor_type in SENSOR_TYPES else None
|
if self._type in SENSOR_TYPES else None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unit_of_measurement(self):
|
def unit_of_measurement(self):
|
||||||
"""Return the unit of measurement."""
|
"""Return the unit of measurement."""
|
||||||
return SENSOR_TYPES[self._sensor_type][1] \
|
return SENSOR_TYPES[self._type][1] \
|
||||||
if self._sensor_type in SENSOR_TYPES else None
|
if self._type in SENSOR_TYPES else None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def icon(self):
|
def icon(self):
|
||||||
"""Return the icon."""
|
"""Return the icon."""
|
||||||
return SENSOR_TYPES[self._sensor_type][2] \
|
return SENSOR_TYPES[self._type][2] \
|
||||||
if self._sensor_type in SENSOR_TYPES else None
|
if self._type in SENSOR_TYPES else None
|
||||||
|
@ -9,7 +9,7 @@ https://home-assistant.io/components/switch.tellduslive/
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from homeassistant.components import tellduslive
|
from homeassistant.components.tellduslive import TelldusLiveEntity
|
||||||
from homeassistant.helpers.entity import ToggleEntity
|
from homeassistant.helpers.entity import ToggleEntity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -19,53 +19,23 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
"""Setup Tellstick switches."""
|
"""Setup Tellstick switches."""
|
||||||
if discovery_info is None:
|
if discovery_info is None:
|
||||||
return
|
return
|
||||||
add_devices(TelldusLiveSwitch(switch) for switch in discovery_info)
|
add_devices(TelldusLiveSwitch(hass, switch) for switch in discovery_info)
|
||||||
|
|
||||||
|
|
||||||
class TelldusLiveSwitch(ToggleEntity):
|
class TelldusLiveSwitch(TelldusLiveEntity, ToggleEntity):
|
||||||
"""Representation of a Tellstick switch."""
|
"""Representation of a Tellstick switch."""
|
||||||
|
|
||||||
def __init__(self, switch_id):
|
|
||||||
"""Initialize the switch."""
|
|
||||||
self._id = switch_id
|
|
||||||
self.update()
|
|
||||||
_LOGGER.debug("created switch %s", self)
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
"""Get the latest date and update the state."""
|
|
||||||
tellduslive.NETWORK.update_switches()
|
|
||||||
self._switch = tellduslive.NETWORK.get_switch(self._id)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def should_poll(self):
|
|
||||||
"""Polling is needed."""
|
|
||||||
return True
|
|
||||||
|
|
||||||
@property
|
|
||||||
def assumed_state(self):
|
|
||||||
"""Return true if unable to access real state of entity."""
|
|
||||||
return True
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
"""Return the name of the switch if any."""
|
|
||||||
return self._switch["name"]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def available(self):
|
|
||||||
"""Return the state of the switch."""
|
|
||||||
return not self._switch.get("offline", False)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self):
|
||||||
"""Return true if switch is on."""
|
"""Return true if switch is on."""
|
||||||
from tellive.live import const
|
return self.device.is_on()
|
||||||
return self._switch["state"] == const.TELLSTICK_TURNON
|
|
||||||
|
|
||||||
def turn_on(self, **kwargs):
|
def turn_on(self, **kwargs):
|
||||||
"""Turn the switch on."""
|
"""Turn the switch on."""
|
||||||
tellduslive.NETWORK.turn_switch_on(self._id)
|
self.device.turn_on()
|
||||||
|
self.changed()
|
||||||
|
|
||||||
def turn_off(self, **kwargs):
|
def turn_off(self, **kwargs):
|
||||||
"""Turn the switch off."""
|
"""Turn the switch off."""
|
||||||
tellduslive.NETWORK.turn_switch_off(self._id)
|
self.device.turn_off()
|
||||||
|
self.changed()
|
||||||
|
@ -4,18 +4,20 @@ Support for Telldus Live.
|
|||||||
For more details about this component, please refer to the documentation at
|
For more details about this component, please refer to the documentation at
|
||||||
https://home-assistant.io/components/tellduslive/
|
https://home-assistant.io/components/tellduslive/
|
||||||
"""
|
"""
|
||||||
|
from datetime import datetime, timedelta
|
||||||
import logging
|
import logging
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
import voluptuous as vol
|
|
||||||
|
|
||||||
|
from homeassistant.const import ATTR_BATTERY_LEVEL, DEVICE_DEFAULT_NAME
|
||||||
from homeassistant.helpers import discovery
|
from homeassistant.helpers import discovery
|
||||||
from homeassistant.util import Throttle
|
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from homeassistant.helpers.event import track_point_in_utc_time
|
||||||
|
from homeassistant.util.dt import utcnow
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
DOMAIN = 'tellduslive'
|
DOMAIN = 'tellduslive'
|
||||||
|
|
||||||
REQUIREMENTS = ['tellive-py==0.5.2']
|
REQUIREMENTS = ['tellduslive==0.1.9']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -23,11 +25,10 @@ CONF_PUBLIC_KEY = 'public_key'
|
|||||||
CONF_PRIVATE_KEY = 'private_key'
|
CONF_PRIVATE_KEY = 'private_key'
|
||||||
CONF_TOKEN = 'token'
|
CONF_TOKEN = 'token'
|
||||||
CONF_TOKEN_SECRET = 'token_secret'
|
CONF_TOKEN_SECRET = 'token_secret'
|
||||||
|
CONF_UPDATE_INTERVAL = 'update_interval'
|
||||||
|
|
||||||
MIN_TIME_BETWEEN_SWITCH_UPDATES = timedelta(minutes=1)
|
MIN_UPDATE_INTERVAL = timedelta(seconds=5)
|
||||||
MIN_TIME_BETWEEN_SENSOR_UPDATES = timedelta(minutes=5)
|
DEFAULT_UPDATE_INTERVAL = timedelta(minutes=1)
|
||||||
|
|
||||||
NETWORK = None
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
DOMAIN: vol.Schema({
|
DOMAIN: vol.Schema({
|
||||||
@ -35,183 +36,190 @@ CONFIG_SCHEMA = vol.Schema({
|
|||||||
vol.Required(CONF_PRIVATE_KEY): cv.string,
|
vol.Required(CONF_PRIVATE_KEY): cv.string,
|
||||||
vol.Required(CONF_TOKEN): cv.string,
|
vol.Required(CONF_TOKEN): cv.string,
|
||||||
vol.Required(CONF_TOKEN_SECRET): cv.string,
|
vol.Required(CONF_TOKEN_SECRET): cv.string,
|
||||||
|
vol.Optional(CONF_UPDATE_INTERVAL, default=DEFAULT_UPDATE_INTERVAL): (
|
||||||
|
vol.All(cv.time_period, vol.Clamp(min=MIN_UPDATE_INTERVAL)))
|
||||||
}),
|
}),
|
||||||
}, extra=vol.ALLOW_EXTRA)
|
}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
|
|
||||||
|
ATTR_LAST_UPDATED = 'time_last_updated'
|
||||||
|
|
||||||
|
|
||||||
def setup(hass, config):
|
def setup(hass, config):
|
||||||
"""Setup the Telldus Live component."""
|
"""Setup the Telldus Live component."""
|
||||||
# fixme: aquire app key and provide authentication using username+password
|
client = TelldusLiveClient(hass, config)
|
||||||
|
|
||||||
global NETWORK
|
if not client.validate_session():
|
||||||
NETWORK = TelldusLiveData(hass, config)
|
|
||||||
|
|
||||||
if not NETWORK.validate_session():
|
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"Authentication Error: "
|
'Authentication Error: '
|
||||||
"Please make sure you have configured your keys "
|
'Please make sure you have configured your keys '
|
||||||
"that can be aquired from https://api.telldus.com/keys/index")
|
'that can be aquired from https://api.telldus.com/keys/index')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
NETWORK.discover()
|
hass.data[DOMAIN] = client
|
||||||
|
client.update(utcnow())
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@Throttle(MIN_TIME_BETWEEN_SWITCH_UPDATES)
|
class TelldusLiveClient(object):
|
||||||
def request_switches():
|
|
||||||
"""Make request to online service."""
|
|
||||||
_LOGGER.debug("Updating switches from Telldus Live")
|
|
||||||
switches = NETWORK.request('devices/list')
|
|
||||||
# Filter out any group of switches.
|
|
||||||
if switches and 'device' in switches:
|
|
||||||
return {switch["id"]: switch for switch in switches['device']
|
|
||||||
if switch["type"] == "device"}
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
@Throttle(MIN_TIME_BETWEEN_SENSOR_UPDATES)
|
|
||||||
def request_sensors():
|
|
||||||
"""Make request to online service."""
|
|
||||||
_LOGGER.debug("Updating sensors from Telldus Live")
|
|
||||||
units = NETWORK.request('sensors/list')
|
|
||||||
# One unit can contain many sensors.
|
|
||||||
if units and 'sensor' in units:
|
|
||||||
return {(unit['id'], sensor['name'], sensor['scale']):
|
|
||||||
dict(unit, data=sensor)
|
|
||||||
for unit in units['sensor']
|
|
||||||
for sensor in unit['data']}
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
class TelldusLiveData(object):
|
|
||||||
"""Get the latest data and update the states."""
|
"""Get the latest data and update the states."""
|
||||||
|
|
||||||
def __init__(self, hass, config):
|
def __init__(self, hass, config):
|
||||||
"""Initialize the Tellus data object."""
|
"""Initialize the Tellus data object."""
|
||||||
|
from tellduslive import Client
|
||||||
|
|
||||||
public_key = config[DOMAIN].get(CONF_PUBLIC_KEY)
|
public_key = config[DOMAIN].get(CONF_PUBLIC_KEY)
|
||||||
private_key = config[DOMAIN].get(CONF_PRIVATE_KEY)
|
private_key = config[DOMAIN].get(CONF_PRIVATE_KEY)
|
||||||
token = config[DOMAIN].get(CONF_TOKEN)
|
token = config[DOMAIN].get(CONF_TOKEN)
|
||||||
token_secret = config[DOMAIN].get(CONF_TOKEN_SECRET)
|
token_secret = config[DOMAIN].get(CONF_TOKEN_SECRET)
|
||||||
|
|
||||||
from tellive.client import LiveClient
|
self.entities = []
|
||||||
|
|
||||||
self._switches = {}
|
|
||||||
self._sensors = {}
|
|
||||||
|
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
self._config = config
|
self._config = config
|
||||||
|
|
||||||
self._client = LiveClient(
|
self._interval = config[DOMAIN].get(CONF_UPDATE_INTERVAL)
|
||||||
public_key=public_key, private_key=private_key, access_token=token,
|
_LOGGER.debug('Update interval %s', self._interval)
|
||||||
access_secret=token_secret)
|
|
||||||
|
self._client = Client(public_key,
|
||||||
|
private_key,
|
||||||
|
token,
|
||||||
|
token_secret)
|
||||||
|
|
||||||
def validate_session(self):
|
def validate_session(self):
|
||||||
"""Make a dummy request to see if the session is valid."""
|
"""Make a request to see if the session is valid."""
|
||||||
response = self.request("user/profile")
|
response = self._client.request_user()
|
||||||
return response and 'email' in response
|
return response and 'email' in response
|
||||||
|
|
||||||
def discover(self):
|
def update(self, now):
|
||||||
"""Update states, will trigger discover."""
|
"""Periodically poll the servers for current state."""
|
||||||
self.update_sensors()
|
_LOGGER.debug('Updating')
|
||||||
self.update_switches()
|
|
||||||
|
|
||||||
def _discover(self, found_devices, component_name):
|
|
||||||
"""Send discovery event if component not yet discovered."""
|
|
||||||
if not found_devices:
|
|
||||||
return
|
|
||||||
|
|
||||||
_LOGGER.info("discovered %d new %s devices",
|
|
||||||
len(found_devices), component_name)
|
|
||||||
|
|
||||||
discovery.load_platform(self._hass, component_name, DOMAIN,
|
|
||||||
found_devices, self._config)
|
|
||||||
|
|
||||||
def request(self, what, **params):
|
|
||||||
"""Send a request to the Tellstick Live API."""
|
|
||||||
from tellive.live import const
|
|
||||||
|
|
||||||
supported_methods = const.TELLSTICK_TURNON \
|
|
||||||
| const.TELLSTICK_TURNOFF \
|
|
||||||
| const.TELLSTICK_TOGGLE \
|
|
||||||
|
|
||||||
# Tellstick device methods not yet supported
|
|
||||||
# | const.TELLSTICK_BELL \
|
|
||||||
# | const.TELLSTICK_DIM \
|
|
||||||
# | const.TELLSTICK_LEARN \
|
|
||||||
# | const.TELLSTICK_EXECUTE \
|
|
||||||
# | const.TELLSTICK_UP \
|
|
||||||
# | const.TELLSTICK_DOWN \
|
|
||||||
# | const.TELLSTICK_STOP
|
|
||||||
|
|
||||||
default_params = {'supportedMethods': supported_methods,
|
|
||||||
'includeValues': 1,
|
|
||||||
'includeScale': 1,
|
|
||||||
'includeIgnored': 0}
|
|
||||||
params.update(default_params)
|
|
||||||
|
|
||||||
# room for improvement: the telllive library doesn't seem to
|
|
||||||
# re-use sessions, instead it opens a new session for each request
|
|
||||||
# this needs to be fixed
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = self._client.request(what, params)
|
self._sync()
|
||||||
_LOGGER.debug("got response %s", response)
|
finally:
|
||||||
return response
|
track_point_in_utc_time(self._hass,
|
||||||
except OSError as error:
|
self.update,
|
||||||
_LOGGER.error("failed to make request to Tellduslive servers: %s",
|
now + self._interval)
|
||||||
error)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def update_devices(self, local_devices, remote_devices, component_name):
|
def _sync(self):
|
||||||
"""Update local device list and discover new devices."""
|
"""Update local list of devices."""
|
||||||
if remote_devices is None:
|
self._client.update()
|
||||||
return local_devices
|
|
||||||
|
|
||||||
remote_ids = remote_devices.keys()
|
def identify_device(device):
|
||||||
local_ids = local_devices.keys()
|
"""Find out what type of HA component to create."""
|
||||||
|
from tellduslive import (DIM, UP, TURNON)
|
||||||
|
if device.methods & DIM:
|
||||||
|
return 'light'
|
||||||
|
elif device.methods & UP:
|
||||||
|
return 'cover'
|
||||||
|
elif device.methods & TURNON:
|
||||||
|
return 'switch'
|
||||||
|
else:
|
||||||
|
_LOGGER.warning('Unidentified device type (methods: %d)',
|
||||||
|
device.methods)
|
||||||
|
return 'switch'
|
||||||
|
|
||||||
added_devices = list(remote_ids - local_ids)
|
def discover(device_id, component):
|
||||||
self._discover(added_devices,
|
"""Discover the component."""
|
||||||
component_name)
|
discovery.load_platform(self._hass,
|
||||||
|
component,
|
||||||
|
DOMAIN,
|
||||||
|
[device_id],
|
||||||
|
self._config)
|
||||||
|
|
||||||
removed_devices = list(local_ids - remote_ids)
|
known_ids = set([entity.device_id for entity in self.entities])
|
||||||
remote_devices.update({id: dict(local_devices[id], offline=True)
|
for device in self._client.devices:
|
||||||
for id in removed_devices})
|
if device.device_id in known_ids:
|
||||||
|
continue
|
||||||
|
if device.is_sensor:
|
||||||
|
for item_id in device.items:
|
||||||
|
discover((device.device_id,) + item_id,
|
||||||
|
'sensor')
|
||||||
|
else:
|
||||||
|
discover(device.device_id,
|
||||||
|
identify_device(device))
|
||||||
|
|
||||||
return remote_devices
|
for entity in self.entities:
|
||||||
|
entity.changed()
|
||||||
|
|
||||||
def update_sensors(self):
|
def device(self, device_id):
|
||||||
"""Update local list of sensors."""
|
"""Return device representation."""
|
||||||
self._sensors = self.update_devices(
|
import tellduslive
|
||||||
self._sensors, request_sensors(), 'sensor')
|
return tellduslive.Device(self._client, device_id)
|
||||||
|
|
||||||
def update_switches(self):
|
def is_available(self, device_id):
|
||||||
"""Update local list of switches."""
|
"""Return device availability."""
|
||||||
self._switches = self.update_devices(
|
return device_id in self._client.device_ids
|
||||||
self._switches, request_switches(), 'switch')
|
|
||||||
|
|
||||||
def _check_request(self, what, **params):
|
|
||||||
"""Make request, check result if successful."""
|
|
||||||
response = self.request(what, **params)
|
|
||||||
return response and response.get('status') == 'success'
|
|
||||||
|
|
||||||
def get_switch(self, switch_id):
|
class TelldusLiveEntity(Entity):
|
||||||
"""Return the switch representation."""
|
"""Base class for all Telldus Live entities."""
|
||||||
return self._switches[switch_id]
|
|
||||||
|
|
||||||
def get_sensor(self, sensor_id):
|
def __init__(self, hass, device_id):
|
||||||
"""Return the sensor representation."""
|
"""Initialize the entity."""
|
||||||
return self._sensors[sensor_id]
|
self._id = device_id
|
||||||
|
self._client = hass.data[DOMAIN]
|
||||||
|
self._client.entities.append(self)
|
||||||
|
_LOGGER.debug('Created device %s', self)
|
||||||
|
|
||||||
def turn_switch_on(self, switch_id):
|
def changed(self):
|
||||||
"""Turn switch off."""
|
"""A property of the device might have changed."""
|
||||||
if self._check_request('device/turnOn', id=switch_id):
|
self.schedule_update_ha_state()
|
||||||
from tellive.live import const
|
|
||||||
self.get_switch(switch_id)['state'] = const.TELLSTICK_TURNON
|
|
||||||
|
|
||||||
def turn_switch_off(self, switch_id):
|
@property
|
||||||
"""Turn switch on."""
|
def device_id(self):
|
||||||
if self._check_request('device/turnOff', id=switch_id):
|
"""Return the id of the device."""
|
||||||
from tellive.live import const
|
return self._id
|
||||||
self.get_switch(switch_id)['state'] = const.TELLSTICK_TURNOFF
|
|
||||||
|
@property
|
||||||
|
def device(self):
|
||||||
|
"""Return the representaion of the device."""
|
||||||
|
return self._client.device(self.device_id)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _state(self):
|
||||||
|
"""Return the state of the device."""
|
||||||
|
return self.device.state
|
||||||
|
|
||||||
|
@property
|
||||||
|
def should_poll(self):
|
||||||
|
"""Polling is not needed."""
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def assumed_state(self):
|
||||||
|
"""Return true if unable to access real state of entity."""
|
||||||
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
"""Return name of device."""
|
||||||
|
return self.device.name or DEVICE_DEFAULT_NAME
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self):
|
||||||
|
"""Return true if device is not offline."""
|
||||||
|
return self._client.is_available(self.device_id)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_state_attributes(self):
|
||||||
|
"""Return the state attributes."""
|
||||||
|
attrs = {}
|
||||||
|
if self._battery_level:
|
||||||
|
attrs[ATTR_BATTERY_LEVEL] = self._battery_level
|
||||||
|
if self._last_updated:
|
||||||
|
attrs[ATTR_LAST_UPDATED] = self._last_updated
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _battery_level(self):
|
||||||
|
"""Return the battery level of a device."""
|
||||||
|
return round(self.device.battery * 100 / 255) \
|
||||||
|
if self.device.battery else None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _last_updated(self):
|
||||||
|
"""Return the last update of a device."""
|
||||||
|
return str(datetime.fromtimestamp(self.device.last_updated)) \
|
||||||
|
if self.device.last_updated else None
|
||||||
|
@ -560,7 +560,7 @@ steamodd==4.21
|
|||||||
tellcore-py==1.1.2
|
tellcore-py==1.1.2
|
||||||
|
|
||||||
# homeassistant.components.tellduslive
|
# homeassistant.components.tellduslive
|
||||||
tellive-py==0.5.2
|
tellduslive==0.1.9
|
||||||
|
|
||||||
# homeassistant.components.sensor.temper
|
# homeassistant.components.sensor.temper
|
||||||
temperusb==1.5.1
|
temperusb==1.5.1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user