core/homeassistant/components/linky/sensor.py

165 lines
4.9 KiB
Python

"""Support for Linky."""
from datetime import timedelta
import json
import logging
from pylinky.client import DAILY, MONTHLY, YEARLY, LinkyClient, PyLinkyError
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import (
ATTR_ATTRIBUTION,
CONF_PASSWORD,
CONF_TIMEOUT,
CONF_USERNAME,
ENERGY_KILO_WATT_HOUR,
)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.event import track_time_interval
import homeassistant.util.dt as dt_util
_LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = timedelta(hours=4)
ICON_ENERGY = "mdi:flash"
CONSUMPTION = "conso"
TIME = "time"
INDEX_CURRENT = -1
INDEX_LAST = -2
ATTRIBUTION = "Data provided by Enedis"
DEFAULT_TIMEOUT = 10
SENSORS = {
"yesterday": ("Linky yesterday", DAILY, INDEX_LAST),
"current_month": ("Linky current month", MONTHLY, INDEX_CURRENT),
"last_month": ("Linky last month", MONTHLY, INDEX_LAST),
"current_year": ("Linky current year", YEARLY, INDEX_CURRENT),
"last_year": ("Linky last year", YEARLY, INDEX_LAST),
}
SENSORS_INDEX_LABEL = 0
SENSORS_INDEX_SCALE = 1
SENSORS_INDEX_WHEN = 2
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int,
}
)
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Configure the platform and add the Linky sensor."""
username = config[CONF_USERNAME]
password = config[CONF_PASSWORD]
timeout = config[CONF_TIMEOUT]
account = LinkyAccount(hass, add_entities, username, password, timeout)
add_entities(account.sensors, True)
class LinkyAccount:
"""Representation of a Linky account."""
def __init__(self, hass, add_entities, username, password, timeout):
"""Initialise the Linky account."""
self._username = username
self.__password = password
self._timeout = timeout
self._data = None
self.sensors = []
self.update_linky_data(dt_util.utcnow())
self.sensors.append(LinkySensor("Linky yesterday", self, DAILY, INDEX_LAST))
self.sensors.append(
LinkySensor("Linky current month", self, MONTHLY, INDEX_CURRENT)
)
self.sensors.append(LinkySensor("Linky last month", self, MONTHLY, INDEX_LAST))
self.sensors.append(
LinkySensor("Linky current year", self, YEARLY, INDEX_CURRENT)
)
self.sensors.append(LinkySensor("Linky last year", self, YEARLY, INDEX_LAST))
track_time_interval(hass, self.update_linky_data, SCAN_INTERVAL)
def update_linky_data(self, event_time):
"""Fetch new state data for the sensor."""
client = LinkyClient(self._username, self.__password, None, self._timeout)
try:
client.login()
client.fetch_data()
self._data = client.get_data()
_LOGGER.debug(json.dumps(self._data, indent=2))
except PyLinkyError as exp:
_LOGGER.error(exp)
finally:
client.close_session()
@property
def username(self):
"""Return the username."""
return self._username
@property
def data(self):
"""Return the data."""
return self._data
class LinkySensor(Entity):
"""Representation of a sensor entity for Linky."""
def __init__(self, name, account: LinkyAccount, scale, when):
"""Initialize the sensor."""
self._name = name
self.__account = account
self._scale = scale
self.__when = when
self._username = account.username
self.__time = None
self.__consumption = None
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def state(self):
"""Return the state of the sensor."""
return self.__consumption
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return ENERGY_KILO_WATT_HOUR
@property
def icon(self):
"""Return the icon of the sensor."""
return ICON_ENERGY
@property
def device_state_attributes(self):
"""Return the state attributes of the sensor."""
return {
ATTR_ATTRIBUTION: ATTRIBUTION,
"time": self.__time,
CONF_USERNAME: self._username,
}
def update(self):
"""Retrieve the new data for the sensor."""
data = self.__account.data[self._scale][self.__when]
self.__consumption = data[CONSUMPTION]
self.__time = data[TIME]
if self._scale is not YEARLY:
year_index = INDEX_CURRENT
if self.__time.endswith("Dec"):
year_index = INDEX_LAST
self.__time += " " + self.__account.data[YEARLY][year_index][TIME]