mirror of
https://github.com/home-assistant/core.git
synced 2025-06-25 01:21:51 +02:00
added rudimentary support for telldus live
This commit is contained in:
@ -15,6 +15,10 @@ omit =
|
||||
homeassistant/components/*/modbus.py
|
||||
|
||||
homeassistant/components/*/tellstick.py
|
||||
|
||||
homeassistant/components/tellduslive.py
|
||||
homeassistant/components/*/tellduslive.py
|
||||
|
||||
homeassistant/components/*/vera.py
|
||||
|
||||
homeassistant/components/ecobee.py
|
||||
|
@ -9,7 +9,8 @@ https://home-assistant.io/components/sensor/
|
||||
import logging
|
||||
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.components import wink, zwave, isy994, verisure, ecobee
|
||||
from homeassistant.components import (wink, zwave, isy994,
|
||||
verisure, ecobee, tellduslive)
|
||||
|
||||
DOMAIN = 'sensor'
|
||||
SCAN_INTERVAL = 30
|
||||
@ -22,7 +23,8 @@ DISCOVERY_PLATFORMS = {
|
||||
zwave.DISCOVER_SENSORS: 'zwave',
|
||||
isy994.DISCOVER_SENSORS: 'isy994',
|
||||
verisure.DISCOVER_SENSORS: 'verisure',
|
||||
ecobee.DISCOVER_SENSORS: 'ecobee'
|
||||
ecobee.DISCOVER_SENSORS: 'ecobee',
|
||||
tellduslive.DISCOVER_SENSORS: 'tellduslive',
|
||||
}
|
||||
|
||||
|
||||
|
100
homeassistant/components/sensor/tellduslive.py
Normal file
100
homeassistant/components/sensor/tellduslive.py
Normal file
@ -0,0 +1,100 @@
|
||||
"""
|
||||
homeassistant.components.sensor.tellduslive
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Shows sensor values from Tellstick Net/Telstick Live.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/sensor.tellduslive/
|
||||
|
||||
"""
|
||||
import logging
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from homeassistant.const import TEMP_CELCIUS, ATTR_BATTERY_LEVEL
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.components import tellduslive
|
||||
|
||||
ATTR_LAST_UPDATED = "time_last_updated"
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
DEPENDENCIES = ['tellduslive']
|
||||
|
||||
SENSOR_TYPE_TEMP = "temp"
|
||||
SENSOR_TYPE_HUMIDITY = "humidity"
|
||||
|
||||
SENSOR_TYPES = {
|
||||
SENSOR_TYPE_TEMP: ['Temperature', TEMP_CELCIUS, "mdi:thermometer"],
|
||||
SENSOR_TYPE_HUMIDITY: ['Humidity', '%', "mdi:water"],
|
||||
}
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
""" Sets up Tellstick sensors. """
|
||||
sensors = tellduslive.NETWORK.get_sensors()
|
||||
devices = []
|
||||
|
||||
for component in sensors:
|
||||
for sensor in component["data"]:
|
||||
# one component can have more than one sensor
|
||||
# (e.g. both humidity and temperature)
|
||||
devices.append(TelldusLiveSensor(component["id"],
|
||||
component["name"],
|
||||
sensor["name"]))
|
||||
add_devices(devices)
|
||||
|
||||
|
||||
class TelldusLiveSensor(Entity):
|
||||
""" Represents a Telldus Live sensor. """
|
||||
|
||||
def __init__(self, sensor_id, sensor_name, sensor_type):
|
||||
self._sensor_id = sensor_id
|
||||
self._sensor_type = sensor_type
|
||||
self._state = None
|
||||
self._name = sensor_name + ' ' + SENSOR_TYPES[sensor_type][0]
|
||||
self._last_update = None
|
||||
self._battery_level = None
|
||||
self.update()
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
""" Returns the name of the device. """
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
""" Returns the state of the device. """
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def state_attributes(self):
|
||||
attrs = dict()
|
||||
if self._battery_level is not None:
|
||||
attrs[ATTR_BATTERY_LEVEL] = self._battery_level
|
||||
if self._last_update is not None:
|
||||
attrs[ATTR_LAST_UPDATED] = self._last_update
|
||||
return attrs
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
return SENSOR_TYPES[self._sensor_type][1]
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
return SENSOR_TYPES[self._sensor_type][2]
|
||||
|
||||
def update(self):
|
||||
values = tellduslive.NETWORK.get_sensor_value(self._sensor_id,
|
||||
self._sensor_type)
|
||||
self._state, self._battery_level, self._last_update = values
|
||||
|
||||
self._state = float(self._state)
|
||||
if self._sensor_type == SENSOR_TYPE_TEMP:
|
||||
self._state = round(self._state, 1)
|
||||
elif self._sensor_type == SENSOR_TYPE_HUMIDITY:
|
||||
self._state = int(round(self._state))
|
||||
|
||||
self._battery_level = round(self._battery_level * 100 / 255) # percent
|
||||
self._battery_level = "%d %%" % self._battery_level
|
||||
|
||||
self._last_update = str(datetime.fromtimestamp(self._last_update))
|
@ -17,7 +17,7 @@ from homeassistant.helpers.entity import ToggleEntity
|
||||
from homeassistant.const import (
|
||||
STATE_ON, SERVICE_TURN_ON, SERVICE_TURN_OFF, ATTR_ENTITY_ID)
|
||||
from homeassistant.components import (
|
||||
group, discovery, wink, isy994, verisure, zwave)
|
||||
group, discovery, wink, isy994, verisure, zwave, tellduslive)
|
||||
|
||||
DOMAIN = 'switch'
|
||||
SCAN_INTERVAL = 30
|
||||
@ -40,6 +40,7 @@ DISCOVERY_PLATFORMS = {
|
||||
isy994.DISCOVER_SWITCHES: 'isy994',
|
||||
verisure.DISCOVER_SWITCHES: 'verisure',
|
||||
zwave.DISCOVER_SWITCHES: 'zwave',
|
||||
tellduslive.DISCOVER_SWITCHES: 'tellduslive',
|
||||
}
|
||||
|
||||
PROP_TO_ATTR = {
|
||||
|
70
homeassistant/components/switch/tellduslive.py
Normal file
70
homeassistant/components/switch/tellduslive.py
Normal file
@ -0,0 +1,70 @@
|
||||
"""
|
||||
homeassistant.components.switch.tellduslive
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Support for Tellstick switches using Tellstick Net and
|
||||
the Telldus Live online service.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/switch.tellduslive/
|
||||
|
||||
"""
|
||||
import logging
|
||||
|
||||
from homeassistant.const import (STATE_ON, STATE_OFF, STATE_UNKNOWN)
|
||||
from homeassistant.components import tellduslive
|
||||
from homeassistant.helpers.entity import ToggleEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
DEPENDENCIES = ['tellduslive']
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
""" Find and return Tellstick switches. """
|
||||
switches = tellduslive.NETWORK.get_switches()
|
||||
add_devices([TelldusLiveSwitch(switch["name"],
|
||||
switch["id"])
|
||||
for switch in switches if switch["type"] == "device"])
|
||||
|
||||
|
||||
class TelldusLiveSwitch(ToggleEntity):
|
||||
""" Represents a Tellstick switch. """
|
||||
|
||||
def __init__(self, name, switch_id):
|
||||
self._name = name
|
||||
self._id = switch_id
|
||||
self._state = STATE_UNKNOWN
|
||||
self.update()
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
""" Tells Home Assistant to poll this entity. """
|
||||
return True
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
""" Returns the name of the switch if any. """
|
||||
return self._name
|
||||
|
||||
def update(self):
|
||||
from tellcore.constants import (
|
||||
TELLSTICK_TURNON, TELLSTICK_TURNOFF)
|
||||
states = {TELLSTICK_TURNON: STATE_ON,
|
||||
TELLSTICK_TURNOFF: STATE_OFF}
|
||||
state = tellduslive.NETWORK.get_switch_state(self._id)
|
||||
self._state = states[state]
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
""" True if switch is on. """
|
||||
self.update()
|
||||
return self._state == STATE_ON
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
""" Turns the switch on. """
|
||||
if tellduslive.NETWORK.turn_switch_on(self._id):
|
||||
self._state = STATE_ON
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
""" Turns the switch off. """
|
||||
if tellduslive.NETWORK.turn_switch_off(self._id):
|
||||
self._state = STATE_OFF
|
210
homeassistant/components/tellduslive.py
Normal file
210
homeassistant/components/tellduslive.py
Normal file
@ -0,0 +1,210 @@
|
||||
"""
|
||||
homeassistant.components.tellduslive
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Tellduslive Component
|
||||
|
||||
This component adds support for the Telldus Live service.
|
||||
Telldus Live is the online service used with Tellstick Net devices.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/sensor.tellduslive/
|
||||
|
||||
Developer access to the Telldus Live service is neccessary
|
||||
API keys can be aquired from https://api.telldus.com/keys/index
|
||||
|
||||
Tellstick Net devices can be auto discovered using the method described in:
|
||||
https://developer.telldus.com/doxygen/html/TellStickNet.html
|
||||
|
||||
It might be possible to communicate with the Tellstick Net device
|
||||
directly, bypassing the Tellstick Live service.
|
||||
This however is poorly documented and yet not fully supported (?) according to
|
||||
http://developer.telldus.se/ticket/114 and
|
||||
https://developer.telldus.com/doxygen/html/TellStickNet.html
|
||||
|
||||
API requests to certain methods, as described in
|
||||
https://api.telldus.com/explore/sensor/info
|
||||
are limited to one request every 10 minutes
|
||||
|
||||
"""
|
||||
|
||||
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):
|
||||
""" Send discovery event if component not yet discovered """
|
||||
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):
|
||||
""" Sends a request to the tellstick live API """
|
||||
|
||||
from tellcore.constants import (
|
||||
TELLSTICK_TURNON, TELLSTICK_TURNOFF, TELLSTICK_TOGGLE)
|
||||
|
||||
supported_methods = TELLSTICK_TURNON \
|
||||
| TELLSTICK_TURNOFF \
|
||||
| TELLSTICK_TOGGLE
|
||||
|
||||
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):
|
||||
""" Make request, check result if successful """
|
||||
return self._request(what, **params) == "success"
|
||||
|
||||
def validate_session(self):
|
||||
""" Make a dummy request to see if the session is valid """
|
||||
try:
|
||||
response = self._request("user/profile")
|
||||
return 'email' in response
|
||||
except RuntimeError:
|
||||
return False
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||
def _update_sensors(self):
|
||||
""" Get the latest sensor data from Telldus Live """
|
||||
_LOGGER.info("Updating sensors from Telldus Live")
|
||||
self._sensors = self._request("sensors/list")["sensor"]
|
||||
|
||||
def _update_switches(self):
|
||||
""" Get the configured switches from Telldus Live"""
|
||||
_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):
|
||||
""" Get the configured sensors """
|
||||
self._update_sensors()
|
||||
return self._sensors
|
||||
|
||||
def get_switches(self):
|
||||
""" Get the configured switches """
|
||||
self._update_switches()
|
||||
return self._switches
|
||||
|
||||
def get_sensor_value(self, sensor_id, sensor_name):
|
||||
""" Get the latest (possibly cached) sensor value """
|
||||
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):
|
||||
""" returns state of switch. """
|
||||
_LOGGER.info("Updating switch state from Telldus Live")
|
||||
return int(self._request("device/info", id=switch_id)["state"])
|
||||
|
||||
def turn_switch_on(self, switch_id):
|
||||
""" turn switch off """
|
||||
return self.check_request("device/turnOn", id=switch_id)
|
||||
|
||||
def turn_switch_off(self, switch_id):
|
||||
""" turn switch on """
|
||||
return self.check_request("device/turnOff", id=switch_id)
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
""" Setup the tellduslive component """
|
||||
|
||||
# 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
|
||||
|
||||
# fixme: validate key?
|
||||
|
||||
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
|
@ -176,6 +176,9 @@ orvibo==1.1.0
|
||||
# homeassistant.components.switch.wemo
|
||||
pywemo==0.3.3
|
||||
|
||||
# homeassistant.components.tellduslive
|
||||
tellive-py==0.5.2
|
||||
|
||||
# homeassistant.components.thermostat.heatmiser
|
||||
heatmiserV3==0.9.1
|
||||
|
||||
|
Reference in New Issue
Block a user