"""Support for FutureNow Ethernet unit outputs as Lights.""" from __future__ import annotations from typing import Any import pyfnip import voluptuous as vol from homeassistant.components.light import ( ATTR_BRIGHTNESS, PLATFORM_SCHEMA, ColorMode, LightEntity, ) from homeassistant.const import CONF_DEVICES, CONF_HOST, CONF_NAME, CONF_PORT from homeassistant.core import HomeAssistant import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType CONF_DRIVER = "driver" CONF_DRIVER_FNIP6X10AD = "FNIP6x10ad" CONF_DRIVER_FNIP8X10A = "FNIP8x10a" CONF_DRIVER_TYPES = [CONF_DRIVER_FNIP6X10AD, CONF_DRIVER_FNIP8X10A] DEVICE_SCHEMA = vol.Schema( { vol.Required(CONF_NAME): cv.string, vol.Optional("dimmable", default=False): cv.boolean, } ) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { vol.Required(CONF_DRIVER): vol.In(CONF_DRIVER_TYPES), vol.Required(CONF_HOST): cv.string, vol.Required(CONF_PORT): cv.port, vol.Required(CONF_DEVICES): {cv.string: DEVICE_SCHEMA}, } ) def setup_platform( hass: HomeAssistant, config: ConfigType, add_entities: AddEntitiesCallback, discovery_info: DiscoveryInfoType | None = None, ) -> None: """Set up the light platform for each FutureNow unit.""" lights = [] for channel, device_config in config[CONF_DEVICES].items(): device = {} device["name"] = device_config[CONF_NAME] device["dimmable"] = device_config["dimmable"] device["channel"] = channel device["driver"] = config[CONF_DRIVER] device["host"] = config[CONF_HOST] device["port"] = config[CONF_PORT] lights.append(FutureNowLight(device)) add_entities(lights, True) def to_futurenow_level(level): """Convert the given Home Assistant light level (0-255) to FutureNow (0-100).""" return round((level * 100) / 255) def to_hass_level(level): """Convert the given FutureNow (0-100) light level to Home Assistant (0-255).""" return int((level * 255) / 100) class FutureNowLight(LightEntity): """Representation of an FutureNow light.""" def __init__(self, device): """Initialize the light.""" self._name = device["name"] self._dimmable = device["dimmable"] self._channel = device["channel"] self._brightness = None self._last_brightness = 255 self._state = None if device["driver"] == CONF_DRIVER_FNIP6X10AD: self._light = pyfnip.FNIP6x2adOutput( device["host"], device["port"], self._channel ) if device["driver"] == CONF_DRIVER_FNIP8X10A: self._light = pyfnip.FNIP8x10aOutput( device["host"], device["port"], self._channel ) @property def name(self): """Return the name of the device if any.""" return self._name @property def is_on(self): """Return true if device is on.""" return self._state @property def brightness(self): """Return the brightness of this light between 0..255.""" return self._brightness @property def color_mode(self) -> ColorMode: """Return the color mode of the light.""" if self._dimmable: return ColorMode.BRIGHTNESS return ColorMode.ONOFF @property def supported_color_modes(self) -> set[ColorMode]: """Flag supported color modes.""" return {self.color_mode} def turn_on(self, **kwargs: Any) -> None: """Turn the light on.""" if self._dimmable: level = kwargs.get(ATTR_BRIGHTNESS, self._last_brightness) else: level = 255 self._light.turn_on(to_futurenow_level(level)) def turn_off(self, **kwargs: Any) -> None: """Turn the light off.""" self._light.turn_off() if self._brightness: self._last_brightness = self._brightness def update(self) -> None: """Fetch new state data for this light.""" state = int(self._light.is_on()) self._state = bool(state) self._brightness = to_hass_level(state)