2015-12-27 11:32:08 +00:00
|
|
|
"""
|
|
|
|
homeassistant.components.tellduslive
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2016-02-02 23:35:53 +00:00
|
|
|
Tellduslive Component.
|
2015-12-27 11:32:08 +00:00
|
|
|
|
2016-02-02 23:35:53 +00:00
|
|
|
For more details about this component, please refer to the documentation at
|
|
|
|
https://home-assistant.io/components/tellduslive/
|
2015-12-27 11:32:08 +00:00
|
|
|
"""
|
|
|
|
from datetime import timedelta
|
|
|
|
import logging
|
|
|
|
|
|
|
|
from homeassistant.loader import get_component
|
|
|
|
from homeassistant import bootstrap
|
|
|
|
from homeassistant.util import Throttle
|
|
|
|
from homeassistant.helpers import validate_config
|
|
|
|
from homeassistant.const import (
|
|
|
|
EVENT_PLATFORM_DISCOVERED, ATTR_SERVICE, ATTR_DISCOVERED)
|
|
|
|
|
|
|
|
DOMAIN = "tellduslive"
|
|
|
|
DISCOVER_SWITCHES = "tellduslive.switches"
|
|
|
|
DISCOVER_SENSORS = "tellduslive.sensors"
|
|
|
|
|
|
|
|
CONF_PUBLIC_KEY = "public_key"
|
|
|
|
CONF_PRIVATE_KEY = "private_key"
|
|
|
|
CONF_TOKEN = "token"
|
|
|
|
CONF_TOKEN_SECRET = "token_secret"
|
|
|
|
|
|
|
|
REQUIREMENTS = ['tellive-py==0.5.2']
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
NETWORK = None
|
|
|
|
|
|
|
|
# Return cached results if last scan was less then this time ago
|
|
|
|
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=600)
|
|
|
|
|
|
|
|
|
|
|
|
class TelldusLiveData(object):
|
|
|
|
""" Gets the latest data and update the states. """
|
|
|
|
|
|
|
|
def __init__(self, hass, config):
|
|
|
|
|
|
|
|
public_key = config[DOMAIN].get(CONF_PUBLIC_KEY)
|
|
|
|
private_key = config[DOMAIN].get(CONF_PRIVATE_KEY)
|
|
|
|
token = config[DOMAIN].get(CONF_TOKEN)
|
|
|
|
token_secret = config[DOMAIN].get(CONF_TOKEN_SECRET)
|
|
|
|
|
|
|
|
from tellive.client import LiveClient
|
|
|
|
from tellive.live import TelldusLive
|
|
|
|
|
|
|
|
self._sensors = []
|
|
|
|
self._switches = []
|
|
|
|
|
|
|
|
self._client = LiveClient(public_key=public_key,
|
|
|
|
private_key=private_key,
|
|
|
|
access_token=token,
|
|
|
|
access_secret=token_secret)
|
|
|
|
self._api = TelldusLive(self._client)
|
|
|
|
|
|
|
|
def update(self, hass, config):
|
2016-02-02 23:35:53 +00:00
|
|
|
""" Send discovery event if component not yet discovered. """
|
2015-12-27 11:32:08 +00:00
|
|
|
self._update_sensors()
|
|
|
|
self._update_switches()
|
|
|
|
for component_name, found_devices, discovery_type in \
|
|
|
|
(('sensor', self._sensors, DISCOVER_SENSORS),
|
|
|
|
('switch', self._switches, DISCOVER_SWITCHES)):
|
|
|
|
if len(found_devices):
|
|
|
|
component = get_component(component_name)
|
|
|
|
bootstrap.setup_component(hass, component.DOMAIN, config)
|
|
|
|
hass.bus.fire(EVENT_PLATFORM_DISCOVERED,
|
|
|
|
{ATTR_SERVICE: discovery_type,
|
|
|
|
ATTR_DISCOVERED: {}})
|
|
|
|
|
|
|
|
def _request(self, what, **params):
|
2016-02-02 23:35:53 +00:00
|
|
|
""" Sends a request to the Tellstick Live API. """
|
2015-12-27 11:32:08 +00:00
|
|
|
|
2015-12-27 17:49:11 +00:00
|
|
|
from tellive.live import const
|
2015-12-27 11:32:08 +00:00
|
|
|
|
2015-12-27 17:49:11 +00:00
|
|
|
supported_methods = const.TELLSTICK_TURNON \
|
|
|
|
| const.TELLSTICK_TURNOFF \
|
|
|
|
| const.TELLSTICK_TOGGLE
|
2015-12-27 11:32:08 +00:00
|
|
|
|
|
|
|
default_params = {'supportedMethods': supported_methods,
|
|
|
|
"includeValues": 1,
|
|
|
|
"includeScale": 1}
|
|
|
|
|
|
|
|
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
|
|
|
|
response = self._client.request(what, params)
|
|
|
|
return response
|
|
|
|
|
|
|
|
def check_request(self, what, **params):
|
2016-02-02 23:35:53 +00:00
|
|
|
""" Make request, check result if successful. """
|
2015-12-27 20:47:49 +00:00
|
|
|
response = self._request(what, **params)
|
|
|
|
return response['status'] == "success"
|
2015-12-27 11:32:08 +00:00
|
|
|
|
|
|
|
def validate_session(self):
|
2016-02-02 23:35:53 +00:00
|
|
|
""" Make a dummy request to see if the session is valid. """
|
2015-12-27 11:32:08 +00:00
|
|
|
try:
|
|
|
|
response = self._request("user/profile")
|
|
|
|
return 'email' in response
|
|
|
|
except RuntimeError:
|
|
|
|
return False
|
|
|
|
|
|
|
|
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
|
|
|
def _update_sensors(self):
|
2016-02-02 23:35:53 +00:00
|
|
|
""" Get the latest sensor data from Telldus Live. """
|
2015-12-27 11:32:08 +00:00
|
|
|
_LOGGER.info("Updating sensors from Telldus Live")
|
|
|
|
self._sensors = self._request("sensors/list")["sensor"]
|
|
|
|
|
|
|
|
def _update_switches(self):
|
2016-02-02 23:35:53 +00:00
|
|
|
""" Get the configured switches from Telldus Live. """
|
2015-12-27 11:32:08 +00:00
|
|
|
_LOGGER.info("Updating switches from Telldus Live")
|
|
|
|
self._switches = self._request("devices/list")["device"]
|
|
|
|
# filter out any group of switches
|
|
|
|
self._switches = [switch for switch in self._switches
|
|
|
|
if switch["type"] == "device"]
|
|
|
|
|
|
|
|
def get_sensors(self):
|
2016-02-02 23:35:53 +00:00
|
|
|
""" Get the configured sensors. """
|
2015-12-27 11:32:08 +00:00
|
|
|
self._update_sensors()
|
|
|
|
return self._sensors
|
|
|
|
|
|
|
|
def get_switches(self):
|
2016-02-02 23:35:53 +00:00
|
|
|
""" Get the configured switches. """
|
2015-12-27 11:32:08 +00:00
|
|
|
self._update_switches()
|
|
|
|
return self._switches
|
|
|
|
|
|
|
|
def get_sensor_value(self, sensor_id, sensor_name):
|
2016-02-02 23:35:53 +00:00
|
|
|
""" Get the latest (possibly cached) sensor value. """
|
2015-12-27 11:32:08 +00:00
|
|
|
self._update_sensors()
|
|
|
|
for component in self._sensors:
|
|
|
|
if component["id"] == sensor_id:
|
|
|
|
for sensor in component["data"]:
|
|
|
|
if sensor["name"] == sensor_name:
|
|
|
|
return (sensor["value"],
|
|
|
|
component["battery"],
|
|
|
|
component["lastUpdated"])
|
|
|
|
|
|
|
|
def get_switch_state(self, switch_id):
|
2016-02-02 23:35:53 +00:00
|
|
|
""" Returns the state of an switch. """
|
2015-12-27 11:32:08 +00:00
|
|
|
_LOGGER.info("Updating switch state from Telldus Live")
|
2015-12-27 20:47:49 +00:00
|
|
|
response = self._request("device/info", id=switch_id)["state"]
|
|
|
|
return int(response)
|
2015-12-27 11:32:08 +00:00
|
|
|
|
|
|
|
def turn_switch_on(self, switch_id):
|
2016-02-02 23:35:53 +00:00
|
|
|
""" Turn switch off. """
|
2015-12-27 11:32:08 +00:00
|
|
|
return self.check_request("device/turnOn", id=switch_id)
|
|
|
|
|
|
|
|
def turn_switch_off(self, switch_id):
|
2016-02-02 23:35:53 +00:00
|
|
|
""" Turn switch on. """
|
2015-12-27 11:32:08 +00:00
|
|
|
return self.check_request("device/turnOff", id=switch_id)
|
|
|
|
|
|
|
|
|
|
|
|
def setup(hass, config):
|
2016-02-02 23:35:53 +00:00
|
|
|
""" Setup the Telldus Live component. """
|
2015-12-27 11:32:08 +00:00
|
|
|
|
|
|
|
# fixme: aquire app key and provide authentication
|
|
|
|
# using username + password
|
|
|
|
if not validate_config(config,
|
|
|
|
{DOMAIN: [CONF_PUBLIC_KEY,
|
|
|
|
CONF_PRIVATE_KEY,
|
|
|
|
CONF_TOKEN,
|
|
|
|
CONF_TOKEN_SECRET]},
|
|
|
|
_LOGGER):
|
|
|
|
_LOGGER.error(
|
|
|
|
"Configuration Error: "
|
|
|
|
"Please make sure you have configured your keys "
|
|
|
|
"that can be aquired from https://api.telldus.com/keys/index")
|
|
|
|
return False
|
|
|
|
|
|
|
|
global NETWORK
|
|
|
|
NETWORK = TelldusLiveData(hass, config)
|
|
|
|
|
|
|
|
if not NETWORK.validate_session():
|
|
|
|
_LOGGER.error(
|
|
|
|
"Authentication Error: "
|
|
|
|
"Please make sure you have configured your keys "
|
|
|
|
"that can be aquired from https://api.telldus.com/keys/index")
|
|
|
|
return False
|
|
|
|
|
|
|
|
NETWORK.update(hass, config)
|
|
|
|
|
|
|
|
return True
|