diff --git a/.coveragerc b/.coveragerc index 83e6971cc6a426..46c7516926bf61 100644 --- a/.coveragerc +++ b/.coveragerc @@ -62,6 +62,7 @@ omit = homeassistant/components/asterisk_cdr/mailbox.py homeassistant/components/asterisk_mbox/* homeassistant/components/asuswrt/device_tracker.py + homeassistant/components/aten_pe/* homeassistant/components/atome/* homeassistant/components/august/* homeassistant/components/aurora_abb_powerone/sensor.py diff --git a/CODEOWNERS b/CODEOWNERS index eb29ee28915738..701bb94448a926 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -32,6 +32,7 @@ homeassistant/components/arcam_fmj/* @elupus homeassistant/components/arduino/* @fabaff homeassistant/components/arest/* @fabaff homeassistant/components/asuswrt/* @kennedyshead +homeassistant/components/aten_pe/* @mtdcr homeassistant/components/atome/* @baqs homeassistant/components/aurora_abb_powerone/* @davet2001 homeassistant/components/auth/* @home-assistant/core diff --git a/homeassistant/components/aten_pe/__init__.py b/homeassistant/components/aten_pe/__init__.py new file mode 100644 index 00000000000000..2a0fb277a48c32 --- /dev/null +++ b/homeassistant/components/aten_pe/__init__.py @@ -0,0 +1 @@ +"""The ATEN PE component.""" diff --git a/homeassistant/components/aten_pe/manifest.json b/homeassistant/components/aten_pe/manifest.json new file mode 100644 index 00000000000000..4f6416dd76c6da --- /dev/null +++ b/homeassistant/components/aten_pe/manifest.json @@ -0,0 +1,12 @@ +{ + "domain": "aten_pe", + "name": "ATEN eco PDUs", + "documentation": "https://www.home-assistant.io/integrations/aten_pe", + "requirements": [ + "atenpdu==0.3.0" + ], + "dependencies": [], + "codeowners": [ + "@mtdcr" + ] +} diff --git a/homeassistant/components/aten_pe/switch.py b/homeassistant/components/aten_pe/switch.py new file mode 100644 index 00000000000000..2ec6ec4b83d544 --- /dev/null +++ b/homeassistant/components/aten_pe/switch.py @@ -0,0 +1,122 @@ +"""The ATEN PE switch component.""" + +import logging + +from atenpdu import AtenPE, AtenPEError +import voluptuous as vol + +from homeassistant.components.switch import ( + DEVICE_CLASS_OUTLET, + PLATFORM_SCHEMA, + SwitchDevice, +) +from homeassistant.const import CONF_HOST, CONF_PORT, CONF_USERNAME +from homeassistant.exceptions import PlatformNotReady +import homeassistant.helpers.config_validation as cv + +_LOGGER = logging.getLogger(__name__) + +CONF_AUTH_KEY = "auth_key" +CONF_COMMUNITY = "community" +CONF_PRIV_KEY = "priv_key" +DEFAULT_COMMUNITY = "private" +DEFAULT_PORT = "161" +DEFAULT_USERNAME = "administrator" + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( + { + vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, + vol.Optional(CONF_COMMUNITY, default=DEFAULT_COMMUNITY): cv.string, + vol.Optional(CONF_USERNAME, default=DEFAULT_USERNAME): cv.string, + vol.Optional(CONF_AUTH_KEY): cv.string, + vol.Optional(CONF_PRIV_KEY): cv.string, + } +) + + +async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): + """Set up the ATEN PE switch.""" + node = config[CONF_HOST] + serv = config[CONF_PORT] + + dev = AtenPE( + node=node, + serv=serv, + community=config[CONF_COMMUNITY], + username=config[CONF_USERNAME], + authkey=config.get(CONF_AUTH_KEY), + privkey=config.get(CONF_PRIV_KEY), + ) + + try: + await hass.async_add_executor_job(dev.initialize) + mac = await dev.deviceMAC() + outlets = dev.outlets() + except AtenPEError as exc: + _LOGGER.error("Failed to initialize %s:%s: %s", node, serv, str(exc)) + raise PlatformNotReady + + switches = [] + async for outlet in outlets: + switches.append(AtenSwitch(dev, mac, outlet.id, outlet.name)) + + async_add_entities(switches) + + +class AtenSwitch(SwitchDevice): + """Represents an ATEN PE switch.""" + + def __init__(self, device, mac, outlet, name): + """Initialize an ATEN PE switch.""" + self._device = device + self._mac = mac + self._outlet = outlet + self._name = name or f"Outlet {outlet}" + self._enabled = False + self._outlet_power = 0.0 + + @property + def unique_id(self) -> str: + """Return a unique ID.""" + return f"{self._mac}-{self._outlet}" + + @property + def name(self) -> str: + """Return the name of the entity.""" + return self._name + + @property + def device_class(self) -> str: + """Return the class of this device, from component DEVICE_CLASSES.""" + return DEVICE_CLASS_OUTLET + + @property + def is_on(self) -> bool: + """Return True if entity is on.""" + return self._enabled + + @property + def current_power_w(self) -> float: + """Return the current power usage in W.""" + return self._outlet_power + + async def async_turn_on(self, **kwargs): + """Turn the switch on.""" + await self._device.setOutletStatus(self._outlet, "on") + self._enabled = True + + async def async_turn_off(self, **kwargs): + """Turn the switch off.""" + await self._device.setOutletStatus(self._outlet, "off") + self._enabled = False + + async def async_update(self): + """Process update from entity.""" + status = await self._device.displayOutletStatus(self._outlet) + if status == "on": + self._enabled = True + self._outlet_power = await self._device.outletPower(self._outlet) + elif status == "off": + self._enabled = False + self._outlet_power = 0.0 diff --git a/requirements_all.txt b/requirements_all.txt index 8f22d229f56110..354745f6957ba4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -239,6 +239,9 @@ asterisk_mbox==0.5.0 # homeassistant.components.upnp async-upnp-client==0.14.11 +# homeassistant.components.aten_pe +atenpdu==0.3.0 + # homeassistant.components.aurora_abb_powerone aurorapy==0.2.6