182 lines
5.3 KiB
Python
182 lines
5.3 KiB
Python
"""The Netio switch component."""
|
|
import logging
|
|
from collections import namedtuple
|
|
from datetime import timedelta
|
|
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.core import callback
|
|
from homeassistant import util
|
|
from homeassistant.components.http import HomeAssistantView
|
|
from homeassistant.const import (
|
|
CONF_HOST, CONF_PORT, CONF_USERNAME, CONF_PASSWORD,
|
|
EVENT_HOMEASSISTANT_STOP, STATE_ON)
|
|
from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA)
|
|
import homeassistant.helpers.config_validation as cv
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
ATTR_START_DATE = 'start_date'
|
|
ATTR_TOTAL_CONSUMPTION_KWH = 'total_energy_kwh'
|
|
|
|
CONF_OUTLETS = 'outlets'
|
|
|
|
DEFAULT_PORT = 1234
|
|
DEFAULT_USERNAME = 'admin'
|
|
Device = namedtuple('device', ['netio', 'entities'])
|
|
DEVICES = {}
|
|
|
|
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
|
|
|
|
REQ_CONF = [CONF_HOST, CONF_OUTLETS]
|
|
|
|
URL_API_NETIO_EP = '/api/netio/{host}'
|
|
|
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|
vol.Required(CONF_HOST): cv.string,
|
|
vol.Required(CONF_PORT, default=DEFAULT_PORT): cv.port,
|
|
vol.Required(CONF_USERNAME, default=DEFAULT_USERNAME): cv.string,
|
|
vol.Required(CONF_PASSWORD): cv.string,
|
|
vol.Optional(CONF_OUTLETS): {cv.string: cv.string},
|
|
})
|
|
|
|
|
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
|
"""Set up the Netio platform."""
|
|
from pynetio import Netio
|
|
|
|
host = config.get(CONF_HOST)
|
|
username = config.get(CONF_USERNAME)
|
|
password = config.get(CONF_PASSWORD)
|
|
port = config.get(CONF_PORT)
|
|
|
|
if not DEVICES:
|
|
hass.http.register_view(NetioApiView)
|
|
|
|
dev = Netio(host, port, username, password)
|
|
|
|
DEVICES[host] = Device(dev, [])
|
|
|
|
# Throttle the update for all Netio switches of one Netio
|
|
dev.update = util.Throttle(MIN_TIME_BETWEEN_SCANS)(dev.update)
|
|
|
|
for key in config[CONF_OUTLETS]:
|
|
switch = NetioSwitch(
|
|
DEVICES[host].netio, key, config[CONF_OUTLETS][key])
|
|
DEVICES[host].entities.append(switch)
|
|
|
|
add_entities(DEVICES[host].entities)
|
|
|
|
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, dispose)
|
|
return True
|
|
|
|
|
|
def dispose(event):
|
|
"""Close connections to Netio Devices."""
|
|
for _, value in DEVICES.items():
|
|
value.netio.stop()
|
|
|
|
|
|
class NetioApiView(HomeAssistantView):
|
|
"""WSGI handler class."""
|
|
|
|
url = URL_API_NETIO_EP
|
|
name = 'api:netio'
|
|
|
|
@callback
|
|
def get(self, request, host):
|
|
"""Request handler."""
|
|
hass = request.app['hass']
|
|
data = request.query
|
|
states, consumptions, cumulated_consumptions, start_dates = \
|
|
[], [], [], []
|
|
|
|
for i in range(1, 5):
|
|
out = 'output%d' % i
|
|
states.append(data.get('%s_state' % out) == STATE_ON)
|
|
consumptions.append(float(data.get('%s_consumption' % out, 0)))
|
|
cumulated_consumptions.append(
|
|
float(data.get('%s_cumulatedConsumption' % out, 0)) / 1000)
|
|
start_dates.append(data.get('%s_consumptionStart' % out, ""))
|
|
|
|
_LOGGER.debug('%s: %s, %s, %s since %s', host, states,
|
|
consumptions, cumulated_consumptions, start_dates)
|
|
|
|
ndev = DEVICES[host].netio
|
|
ndev.consumptions = consumptions
|
|
ndev.cumulated_consumptions = cumulated_consumptions
|
|
ndev.states = states
|
|
ndev.start_dates = start_dates
|
|
|
|
for dev in DEVICES[host].entities:
|
|
hass.async_create_task(dev.async_update_ha_state())
|
|
|
|
return self.json(True)
|
|
|
|
|
|
class NetioSwitch(SwitchDevice):
|
|
"""Provide a Netio linked switch."""
|
|
|
|
def __init__(self, netio, outlet, name):
|
|
"""Initialize the Netio switch."""
|
|
self._name = name
|
|
self.outlet = outlet
|
|
self.netio = netio
|
|
|
|
@property
|
|
def name(self):
|
|
"""Return the device's name."""
|
|
return self._name
|
|
|
|
@property
|
|
def available(self):
|
|
"""Return true if entity is available."""
|
|
return not hasattr(self, 'telnet')
|
|
|
|
def turn_on(self, **kwargs):
|
|
"""Turn switch on."""
|
|
self._set(True)
|
|
|
|
def turn_off(self, **kwargs):
|
|
"""Turn switch off."""
|
|
self._set(False)
|
|
|
|
def _set(self, value):
|
|
val = list('uuuu')
|
|
val[int(self.outlet) - 1] = '1' if value else '0'
|
|
self.netio.get('port list %s' % ''.join(val))
|
|
self.netio.states[int(self.outlet) - 1] = value
|
|
self.schedule_update_ha_state()
|
|
|
|
@property
|
|
def is_on(self):
|
|
"""Return the switch's status."""
|
|
return self.netio.states[int(self.outlet) - 1]
|
|
|
|
def update(self):
|
|
"""Update the state."""
|
|
self.netio.update()
|
|
|
|
@property
|
|
def state_attributes(self):
|
|
"""Return optional state attributes."""
|
|
return {
|
|
ATTR_TOTAL_CONSUMPTION_KWH: self.cumulated_consumption_kwh,
|
|
ATTR_START_DATE: self.start_date.split('|')[0]
|
|
}
|
|
|
|
@property
|
|
def current_power_w(self):
|
|
"""Return actual power."""
|
|
return self.netio.consumptions[int(self.outlet) - 1]
|
|
|
|
@property
|
|
def cumulated_consumption_kwh(self):
|
|
"""Return the total enerygy consumption since start_date."""
|
|
return self.netio.cumulated_consumptions[int(self.outlet) - 1]
|
|
|
|
@property
|
|
def start_date(self):
|
|
"""Point in time when the energy accumulation started."""
|
|
return self.netio.start_dates[int(self.outlet) - 1]
|