Tellduslive refactoring (#18780)
* move component to a package * move TelldusLiveEntry to separate file * refactor * move entities from a shared container * using the dispatch helper instead for communication between component and platforms * updated covereagerc and codeowners * suggestions from MartinHjelmare * don't make update async * "Strip is good!"
This commit is contained in:
parent
a6511fc0b9
commit
d6a4e106a9
10 changed files with 168 additions and 153 deletions
|
@ -329,7 +329,8 @@ omit =
|
|||
homeassistant/components/tahoma.py
|
||||
homeassistant/components/*/tahoma.py
|
||||
|
||||
homeassistant/components/tellduslive.py
|
||||
homeassistant/components/tellduslive/__init__.py
|
||||
homeassistant/components/tellduslive/entry.py
|
||||
homeassistant/components/*/tellduslive.py
|
||||
|
||||
homeassistant/components/tellstick.py
|
||||
|
|
|
@ -236,8 +236,8 @@ homeassistant/components/*/simplisafe.py @bachya
|
|||
# T
|
||||
homeassistant/components/tahoma.py @philklei
|
||||
homeassistant/components/*/tahoma.py @philklei
|
||||
homeassistant/components/tellduslive.py @molobrakos @fredrike
|
||||
homeassistant/components/*/tellduslive.py @molobrakos @fredrike
|
||||
homeassistant/components/tellduslive/*.py @fredrike
|
||||
homeassistant/components/*/tellduslive.py @fredrike
|
||||
homeassistant/components/tesla.py @zabuldon
|
||||
homeassistant/components/*/tesla.py @zabuldon
|
||||
homeassistant/components/thethingsnetwork.py @fabaff
|
||||
|
|
|
@ -9,8 +9,9 @@ https://home-assistant.io/components/binary_sensor.tellduslive/
|
|||
"""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.tellduslive import TelldusLiveEntity
|
||||
from homeassistant.components import tellduslive
|
||||
from homeassistant.components.binary_sensor import BinarySensorDevice
|
||||
from homeassistant.components.tellduslive.entry import TelldusLiveEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -19,8 +20,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||
"""Set up Tellstick sensors."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
client = hass.data[tellduslive.DOMAIN]
|
||||
add_entities(
|
||||
TelldusLiveSensor(hass, binary_sensor)
|
||||
TelldusLiveSensor(client, binary_sensor)
|
||||
for binary_sensor in discovery_info
|
||||
)
|
||||
|
||||
|
|
|
@ -8,8 +8,9 @@ https://home-assistant.io/components/cover.tellduslive/
|
|||
"""
|
||||
import logging
|
||||
|
||||
from homeassistant.components import tellduslive
|
||||
from homeassistant.components.cover import CoverDevice
|
||||
from homeassistant.components.tellduslive import TelldusLiveEntity
|
||||
from homeassistant.components.tellduslive.entry import TelldusLiveEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -19,7 +20,8 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||
if discovery_info is None:
|
||||
return
|
||||
|
||||
add_entities(TelldusLiveCover(hass, cover) for cover in discovery_info)
|
||||
client = hass.data[tellduslive.DOMAIN]
|
||||
add_entities(TelldusLiveCover(client, cover) for cover in discovery_info)
|
||||
|
||||
|
||||
class TelldusLiveCover(TelldusLiveEntity, CoverDevice):
|
||||
|
@ -33,14 +35,11 @@ class TelldusLiveCover(TelldusLiveEntity, CoverDevice):
|
|||
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()
|
||||
|
|
|
@ -8,9 +8,10 @@ https://home-assistant.io/components/light.tellduslive/
|
|||
"""
|
||||
import logging
|
||||
|
||||
from homeassistant.components import tellduslive
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, Light)
|
||||
from homeassistant.components.tellduslive import TelldusLiveEntity
|
||||
from homeassistant.components.tellduslive.entry import TelldusLiveEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -19,21 +20,21 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||
"""Set up the Tellstick Net lights."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
add_entities(TelldusLiveLight(hass, light) for light in discovery_info)
|
||||
client = hass.data[tellduslive.DOMAIN]
|
||||
add_entities(TelldusLiveLight(client, light) for light in discovery_info)
|
||||
|
||||
|
||||
class TelldusLiveLight(TelldusLiveEntity, Light):
|
||||
"""Representation of a Tellstick Net light."""
|
||||
|
||||
def __init__(self, hass, device_id):
|
||||
def __init__(self, client, device_id):
|
||||
"""Initialize the Tellstick Net light."""
|
||||
super().__init__(hass, device_id)
|
||||
super().__init__(client, device_id)
|
||||
self._last_brightness = self.brightness
|
||||
|
||||
def changed(self):
|
||||
"""Define a property of the device that might have changed."""
|
||||
self._last_brightness = self.brightness
|
||||
super().changed()
|
||||
|
||||
@property
|
||||
def brightness(self):
|
||||
|
|
|
@ -6,7 +6,8 @@ https://home-assistant.io/components/sensor.tellduslive/
|
|||
"""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.tellduslive import TelldusLiveEntity
|
||||
from homeassistant.components import tellduslive
|
||||
from homeassistant.components.tellduslive.entry import TelldusLiveEntity
|
||||
from homeassistant.const import (
|
||||
DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_ILLUMINANCE, DEVICE_CLASS_TEMPERATURE,
|
||||
TEMP_CELSIUS)
|
||||
|
@ -27,8 +28,8 @@ SENSOR_TYPE_DEW_POINT = 'dewp'
|
|||
SENSOR_TYPE_BAROMETRIC_PRESSURE = 'barpress'
|
||||
|
||||
SENSOR_TYPES = {
|
||||
SENSOR_TYPE_TEMPERATURE: ['Temperature', TEMP_CELSIUS, None,
|
||||
DEVICE_CLASS_TEMPERATURE],
|
||||
SENSOR_TYPE_TEMPERATURE:
|
||||
['Temperature', TEMP_CELSIUS, None, DEVICE_CLASS_TEMPERATURE],
|
||||
SENSOR_TYPE_HUMIDITY: ['Humidity', '%', None, DEVICE_CLASS_HUMIDITY],
|
||||
SENSOR_TYPE_RAINRATE: ['Rain rate', 'mm/h', 'mdi:water', None],
|
||||
SENSOR_TYPE_RAINTOTAL: ['Rain total', 'mm', 'mdi:water', None],
|
||||
|
@ -39,7 +40,7 @@ SENSOR_TYPES = {
|
|||
SENSOR_TYPE_WATT: ['Power', 'W', '', None],
|
||||
SENSOR_TYPE_LUMINANCE: ['Luminance', 'lx', None, DEVICE_CLASS_ILLUMINANCE],
|
||||
SENSOR_TYPE_DEW_POINT:
|
||||
['Dew Point', TEMP_CELSIUS, None, DEVICE_CLASS_TEMPERATURE],
|
||||
['Dew Point', TEMP_CELSIUS, None, DEVICE_CLASS_TEMPERATURE],
|
||||
SENSOR_TYPE_BAROMETRIC_PRESSURE: ['Barometric Pressure', 'kPa', '', None],
|
||||
}
|
||||
|
||||
|
@ -48,7 +49,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||
"""Set up the Tellstick sensors."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
add_entities(TelldusLiveSensor(hass, sensor) for sensor in discovery_info)
|
||||
client = hass.data[tellduslive.DOMAIN]
|
||||
add_entities(
|
||||
TelldusLiveSensor(client, sensor) for sensor in discovery_info)
|
||||
|
||||
|
||||
class TelldusLiveSensor(TelldusLiveEntity):
|
||||
|
@ -87,9 +90,7 @@ class TelldusLiveSensor(TelldusLiveEntity):
|
|||
@property
|
||||
def name(self):
|
||||
"""Return the name of the sensor."""
|
||||
return '{} {}'.format(
|
||||
super().name,
|
||||
self.quantity_name or '')
|
||||
return '{} {}'.format(super().name, self.quantity_name or '').strip()
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
|
|
|
@ -9,7 +9,8 @@ https://home-assistant.io/components/switch.tellduslive/
|
|||
"""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.tellduslive import TelldusLiveEntity
|
||||
from homeassistant.components import tellduslive
|
||||
from homeassistant.components.tellduslive.entry import TelldusLiveEntity
|
||||
from homeassistant.helpers.entity import ToggleEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -19,7 +20,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||
"""Set up Tellstick switches."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
add_entities(TelldusLiveSwitch(hass, switch) for switch in discovery_info)
|
||||
client = hass.data[tellduslive.DOMAIN]
|
||||
add_entities(
|
||||
TelldusLiveSwitch(client, switch) for switch in discovery_info)
|
||||
|
||||
|
||||
class TelldusLiveSwitch(TelldusLiveEntity, ToggleEntity):
|
||||
|
@ -33,9 +36,7 @@ class TelldusLiveSwitch(TelldusLiveEntity, ToggleEntity):
|
|||
def turn_on(self, **kwargs):
|
||||
"""Turn the switch on."""
|
||||
self.device.turn_on()
|
||||
self.changed()
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
"""Turn the switch off."""
|
||||
self.device.turn_off()
|
||||
self.changed()
|
||||
|
|
|
@ -4,25 +4,22 @@ Support for Telldus Live.
|
|||
For more details about this component, please refer to the documentation at
|
||||
https://home-assistant.io/components/tellduslive/
|
||||
"""
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.discovery import SERVICE_TELLDUSLIVE
|
||||
from homeassistant.const import (
|
||||
ATTR_BATTERY_LEVEL, CONF_HOST, CONF_TOKEN, DEVICE_DEFAULT_NAME,
|
||||
EVENT_HOMEASSISTANT_START)
|
||||
from homeassistant.const import CONF_HOST, CONF_TOKEN
|
||||
from homeassistant.helpers import discovery
|
||||
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
|
||||
from homeassistant.helpers.dispatcher import dispatcher_send
|
||||
from homeassistant.helpers.event import track_time_interval
|
||||
from homeassistant.util.json import load_json, save_json
|
||||
|
||||
APPLICATION_NAME = 'Home Assistant'
|
||||
from .const import DOMAIN, SIGNAL_UPDATE_ENTITY
|
||||
|
||||
DOMAIN = 'tellduslive'
|
||||
APPLICATION_NAME = 'Home Assistant'
|
||||
|
||||
REQUIREMENTS = ['tellduslive==0.10.4']
|
||||
|
||||
|
@ -48,9 +45,6 @@ CONFIG_SCHEMA = vol.Schema({
|
|||
}),
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
|
||||
ATTR_LAST_UPDATED = 'time_last_updated'
|
||||
|
||||
CONFIG_INSTRUCTIONS = """
|
||||
To link your TelldusLive account:
|
||||
|
||||
|
@ -146,7 +140,7 @@ def setup(hass, config, session=None):
|
|||
if not supports_local_api(device):
|
||||
_LOGGER.debug('Tellstick does not support local API')
|
||||
# Configure the cloud service
|
||||
hass.async_add_job(request_configuration)
|
||||
hass.add_job(request_configuration)
|
||||
return
|
||||
|
||||
_LOGGER.debug('Tellstick does support local API')
|
||||
|
@ -189,18 +183,17 @@ def setup(hass, config, session=None):
|
|||
return True
|
||||
|
||||
if not session.is_authorized:
|
||||
_LOGGER.error(
|
||||
'Authentication Error')
|
||||
_LOGGER.error('Authentication Error')
|
||||
return False
|
||||
|
||||
client = TelldusLiveClient(hass, config, session)
|
||||
|
||||
hass.data[DOMAIN] = client
|
||||
client.update()
|
||||
|
||||
if session:
|
||||
client.update()
|
||||
else:
|
||||
hass.bus.listen(EVENT_HOMEASSISTANT_START, client.update)
|
||||
interval = config.get(DOMAIN, {}).get(CONF_UPDATE_INTERVAL,
|
||||
DEFAULT_UPDATE_INTERVAL)
|
||||
_LOGGER.debug('Update interval %s', interval)
|
||||
track_time_interval(hass, client.update, interval)
|
||||
|
||||
return True
|
||||
|
||||
|
@ -210,27 +203,15 @@ class TelldusLiveClient:
|
|||
|
||||
def __init__(self, hass, config, session):
|
||||
"""Initialize the Tellus data object."""
|
||||
self.entities = []
|
||||
self._known_devices = set()
|
||||
|
||||
self._hass = hass
|
||||
self._config = config
|
||||
|
||||
self._interval = config.get(DOMAIN, {}).get(
|
||||
CONF_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL)
|
||||
_LOGGER.debug('Update interval %s', self._interval)
|
||||
self._client = session
|
||||
|
||||
def update(self, *args):
|
||||
"""Periodically poll the servers for current state."""
|
||||
_LOGGER.debug('Updating')
|
||||
try:
|
||||
self._sync()
|
||||
finally:
|
||||
track_point_in_utc_time(
|
||||
self._hass, self.update, utcnow() + self._interval)
|
||||
|
||||
def _sync(self):
|
||||
"""Update local list of devices."""
|
||||
_LOGGER.debug('Updating')
|
||||
if not self._client.update():
|
||||
_LOGGER.warning('Failed request')
|
||||
|
||||
|
@ -254,9 +235,8 @@ class TelldusLiveClient:
|
|||
discovery.load_platform(
|
||||
self._hass, component, DOMAIN, [device_id], self._config)
|
||||
|
||||
known_ids = {entity.device_id for entity in self.entities}
|
||||
for device in self._client.devices:
|
||||
if device.device_id in known_ids:
|
||||
if device.device_id in self._known_devices:
|
||||
continue
|
||||
if device.is_sensor:
|
||||
for item in device.items:
|
||||
|
@ -265,9 +245,9 @@ class TelldusLiveClient:
|
|||
else:
|
||||
discover(device.device_id,
|
||||
identify_device(device))
|
||||
self._known_devices.add(device.device_id)
|
||||
|
||||
for entity in self.entities:
|
||||
entity.changed()
|
||||
dispatcher_send(self._hass, SIGNAL_UPDATE_ENTITY)
|
||||
|
||||
def device(self, device_id):
|
||||
"""Return device representation."""
|
||||
|
@ -276,91 +256,3 @@ class TelldusLiveClient:
|
|||
def is_available(self, device_id):
|
||||
"""Return device availability."""
|
||||
return device_id in self._client.device_ids
|
||||
|
||||
|
||||
class TelldusLiveEntity(Entity):
|
||||
"""Base class for all Telldus Live entities."""
|
||||
|
||||
def __init__(self, hass, device_id):
|
||||
"""Initialize the entity."""
|
||||
self._id = device_id
|
||||
self._client = hass.data[DOMAIN]
|
||||
self._client.entities.append(self)
|
||||
self._name = self.device.name
|
||||
_LOGGER.debug('Created device %s', self)
|
||||
|
||||
def changed(self):
|
||||
"""Return the property of the device might have changed."""
|
||||
if self.device.name:
|
||||
self._name = self.device.name
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
@property
|
||||
def device_id(self):
|
||||
"""Return the id of the device."""
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def device(self):
|
||||
"""Return the representation 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):
|
||||
"""Return the polling state."""
|
||||
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._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."""
|
||||
from tellduslive import (BATTERY_LOW,
|
||||
BATTERY_UNKNOWN,
|
||||
BATTERY_OK)
|
||||
if self.device.battery == BATTERY_LOW:
|
||||
return 1
|
||||
if self.device.battery == BATTERY_UNKNOWN:
|
||||
return None
|
||||
if self.device.battery == BATTERY_OK:
|
||||
return 100
|
||||
return self.device.battery # Percentage
|
||||
|
||||
@property
|
||||
def _last_updated(self):
|
||||
"""Return the last update of a device."""
|
||||
return str(datetime.fromtimestamp(self.device.lastUpdated)) \
|
||||
if self.device.lastUpdated else None
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str:
|
||||
"""Return a unique ID."""
|
||||
return self._id
|
5
homeassistant/components/tellduslive/const.py
Normal file
5
homeassistant/components/tellduslive/const.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
"""Consts used by TelldusLive."""
|
||||
|
||||
DOMAIN = 'tellduslive'
|
||||
|
||||
SIGNAL_UPDATE_ENTITY = 'tellduslive_update'
|
113
homeassistant/components/tellduslive/entry.py
Normal file
113
homeassistant/components/tellduslive/entry.py
Normal file
|
@ -0,0 +1,113 @@
|
|||
"""Base Entity for all TelldusLiveEntities."""
|
||||
from datetime import datetime
|
||||
import logging
|
||||
|
||||
from homeassistant.const import ATTR_BATTERY_LEVEL, DEVICE_DEFAULT_NAME
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
from .const import SIGNAL_UPDATE_ENTITY
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ATTR_LAST_UPDATED = 'time_last_updated'
|
||||
|
||||
|
||||
class TelldusLiveEntity(Entity):
|
||||
"""Base class for all Telldus Live entities."""
|
||||
|
||||
def __init__(self, client, device_id):
|
||||
"""Initialize the entity."""
|
||||
self._id = device_id
|
||||
self._client = client
|
||||
self._name = self.device.name
|
||||
self._async_unsub_dispatcher_connect = None
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Call when entity is added to hass."""
|
||||
_LOGGER.debug('Created device %s', self)
|
||||
self._async_unsub_dispatcher_connect = async_dispatcher_connect(
|
||||
self.hass, SIGNAL_UPDATE_ENTITY, self._update_callback)
|
||||
|
||||
async def async_will_remove_from_hass(self):
|
||||
"""Disconnect dispatcher listener when removed."""
|
||||
if self._async_unsub_dispatcher_connect:
|
||||
self._async_unsub_dispatcher_connect()
|
||||
|
||||
@callback
|
||||
def _update_callback(self):
|
||||
"""Return the property of the device might have changed."""
|
||||
if self.device.name:
|
||||
self._name = self.device.name
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
@property
|
||||
def device_id(self):
|
||||
"""Return the id of the device."""
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def device(self):
|
||||
"""Return the representation 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):
|
||||
"""Return the polling state."""
|
||||
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._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."""
|
||||
from tellduslive import (BATTERY_LOW,
|
||||
BATTERY_UNKNOWN,
|
||||
BATTERY_OK)
|
||||
if self.device.battery == BATTERY_LOW:
|
||||
return 1
|
||||
if self.device.battery == BATTERY_UNKNOWN:
|
||||
return None
|
||||
if self.device.battery == BATTERY_OK:
|
||||
return 100
|
||||
return self.device.battery # Percentage
|
||||
|
||||
@property
|
||||
def _last_updated(self):
|
||||
"""Return the last update of a device."""
|
||||
return str(datetime.fromtimestamp(self.device.lastUpdated)) \
|
||||
if self.device.lastUpdated else None
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str:
|
||||
"""Return a unique ID."""
|
||||
return self._id
|
Loading…
Add table
Reference in a new issue