165 lines
4.9 KiB
Python
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]
|