"""Support for consuming values for the Volkszaehler API.""" from datetime import timedelta import logging import voluptuous as vol from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.const import ( CONF_HOST, CONF_NAME, CONF_PORT, CONF_MONITORED_CONDITIONS, POWER_WATT, ENERGY_WATT_HOUR) from homeassistant.exceptions import PlatformNotReady from homeassistant.helpers.aiohttp_client import async_get_clientsession import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle _LOGGER = logging.getLogger(__name__) CONF_UUID = 'uuid' DEFAULT_HOST = 'localhost' DEFAULT_NAME = 'Volkszaehler' DEFAULT_PORT = 80 MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=1) SENSOR_TYPES = { 'average': ['Average', POWER_WATT, 'mdi:power-off'], 'consumption': ['Consumption', ENERGY_WATT_HOUR, 'mdi:power-plug'], 'max': ['Max', POWER_WATT, 'mdi:arrow-up'], 'min': ['Min', POWER_WATT, 'mdi:arrow-down'], } PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_UUID): cv.string, vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, vol.Optional(CONF_MONITORED_CONDITIONS, default=['average']): vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), }) async def async_setup_platform( hass, config, async_add_entities, discovery_info=None): """Set up the Volkszaehler sensors.""" from volkszaehler import Volkszaehler host = config[CONF_HOST] name = config[CONF_NAME] port = config[CONF_PORT] uuid = config[CONF_UUID] conditions = config[CONF_MONITORED_CONDITIONS] session = async_get_clientsession(hass) vz_api = VolkszaehlerData( Volkszaehler(hass.loop, session, uuid, host=host, port=port)) await vz_api.async_update() if vz_api.api.data is None: raise PlatformNotReady dev = [] for condition in conditions: dev.append(VolkszaehlerSensor(vz_api, name, condition)) async_add_entities(dev, True) class VolkszaehlerSensor(Entity): """Implementation of a Volkszaehler sensor.""" def __init__(self, vz_api, name, sensor_type): """Initialize the Volkszaehler sensor.""" self.vz_api = vz_api self._name = name self.type = sensor_type self._state = None @property def name(self): """Return the name of the sensor.""" return '{} {}'.format(self._name, SENSOR_TYPES[self.type][0]) @property def icon(self): """Icon to use in the frontend, if any.""" return SENSOR_TYPES[self.type][2] @property def unit_of_measurement(self): """Return the unit the value is expressed in.""" return SENSOR_TYPES[self.type][1] @property def available(self): """Could the device be accessed during the last update call.""" return self.vz_api.available @property def state(self): """Return the state of the resources.""" return self._state async def async_update(self): """Get the latest data from REST API.""" await self.vz_api.async_update() if self.vz_api.api.data is not None: self._state = round(getattr(self.vz_api.api, self.type), 2) class VolkszaehlerData: """The class for handling the data retrieval from the Volkszaehler API.""" def __init__(self, api): """Initialize the data object.""" self.api = api self.available = True @Throttle(MIN_TIME_BETWEEN_UPDATES) async def async_update(self): """Get the latest data from the Volkszaehler REST API.""" from volkszaehler.exceptions import VolkszaehlerApiConnectionError try: await self.api.get_data() self.available = True except VolkszaehlerApiConnectionError: _LOGGER.error("Unable to fetch data from the Volkszaehler API") self.available = False