core/homeassistant/components/netio/switch.py

178 lines
4.8 KiB
Python
Raw Normal View History

"""The Netio switch component."""
2021-08-16 21:25:41 +00:00
from __future__ import annotations
from collections import namedtuple
from datetime import timedelta
2019-12-03 23:46:26 +00:00
import logging
2016-09-11 07:22:08 +00:00
2019-12-03 23:46:26 +00:00
from pynetio import Netio
2016-09-11 07:22:08 +00:00
import voluptuous as vol
from homeassistant import util
from homeassistant.components.http import HomeAssistantView
from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchEntity
2016-09-11 07:22:08 +00:00
from homeassistant.const import (
2019-07-31 19:25:30 +00:00
CONF_HOST,
2019-12-03 23:46:26 +00:00
CONF_PASSWORD,
2019-07-31 19:25:30 +00:00
CONF_PORT,
CONF_USERNAME,
EVENT_HOMEASSISTANT_STOP,
STATE_ON,
)
from homeassistant.core import HomeAssistant, callback
2016-09-11 07:22:08 +00:00
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
2016-09-11 07:22:08 +00:00
_LOGGER = logging.getLogger(__name__)
2019-07-31 19:25:30 +00:00
ATTR_START_DATE = "start_date"
ATTR_TOTAL_CONSUMPTION_KWH = "total_energy_kwh"
2019-07-31 19:25:30 +00:00
CONF_OUTLETS = "outlets"
2016-09-11 07:22:08 +00:00
DEFAULT_PORT = 1234
2019-07-31 19:25:30 +00:00
DEFAULT_USERNAME = "admin"
2021-08-16 21:25:41 +00:00
Device = namedtuple("Device", ["netio", "entities"])
DEVICES: dict[str, Device] = {}
2016-09-11 07:22:08 +00:00
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
2016-09-11 07:22:08 +00:00
REQ_CONF = [CONF_HOST, CONF_OUTLETS]
2019-07-31 19:25:30 +00:00
URL_API_NETIO_EP = "/api/netio/{host}"
2016-09-11 07:22:08 +00:00
2019-07-31 19:25:30 +00:00
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},
}
)
2016-09-11 07:22:08 +00:00
def setup_platform(
hass: HomeAssistant,
config: ConfigType,
add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up the Netio platform."""
host = config[CONF_HOST]
username = config[CONF_USERNAME]
password = config[CONF_PASSWORD]
port = config[CONF_PORT]
2016-09-11 07:22:08 +00:00
if not DEVICES:
hass.http.register_view(NetioApiView)
2016-09-11 07:22:08 +00:00
dev = Netio(host, port, username, password)
2016-09-11 07:22:08 +00:00
DEVICES[host] = Device(dev, [])
# Throttle the update for all Netio switches of one Netio
2016-09-11 07:22:08 +00:00
dev.update = util.Throttle(MIN_TIME_BETWEEN_SCANS)(dev.update)
2016-09-11 07:22:08 +00:00
for key in config[CONF_OUTLETS]:
2019-07-31 19:25:30 +00:00
switch = NetioSwitch(DEVICES[host].netio, key, config[CONF_OUTLETS][key])
2016-09-11 07:22:08 +00:00
DEVICES[host].entities.append(switch)
add_entities(DEVICES[host].entities)
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, dispose)
def dispose(event):
"""Close connections to Netio Devices."""
for value in DEVICES.values():
value.netio.stop()
class NetioApiView(HomeAssistantView):
"""WSGI handler class."""
url = URL_API_NETIO_EP
2019-07-31 19:25:30 +00:00
name = "api:netio"
@callback
def get(self, request, host):
"""Request handler."""
data = request.query
2019-07-31 19:25:30 +00:00
states, consumptions, cumulated_consumptions, start_dates = [], [], [], []
for i in range(1, 5):
2019-07-31 19:25:30 +00:00
out = "output%d" % i
2021-07-12 22:12:55 +00:00
states.append(data.get(f"{out}_state") == STATE_ON)
consumptions.append(float(data.get(f"{out}_consumption", 0)))
cumulated_consumptions.append(
2021-07-12 22:12:55 +00:00
float(data.get(f"{out}_cumulatedConsumption", 0)) / 1000
2019-07-31 19:25:30 +00:00
)
2021-07-12 22:12:55 +00:00
start_dates.append(data.get(f"{out}_consumptionStart", ""))
2019-07-31 19:25:30 +00:00
_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:
dev.async_write_ha_state()
return self.json(True)
class NetioSwitch(SwitchEntity):
"""Provide a Netio linked switch."""
def __init__(self, netio, outlet, name):
2017-05-03 08:11:39 +00:00
"""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."""
2019-07-31 19:25:30 +00:00
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):
2019-07-31 19:25:30 +00:00
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()