"""sACN-Zahlenfelder eines ninstrip-Geraets: Universe und Startslot.""" from __future__ import annotations from homeassistant.components.number import NumberEntity, NumberMode from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from .coordinator import NinstripConfigEntry, NinstripCoordinator from .entity import NinstripSacnEntity PARALLEL_UPDATES = 0 # Kanaele je Pixel, falls das Geraet sie nicht meldet. Die Firmware stellt fest # drei ein (R, G, B) - so senden LedFx, xLights und Resolume. _KANAELE_VORGABE = 3 async def async_setup_entry( hass: HomeAssistant, entry: NinstripConfigEntry, async_add_entities: AddConfigEntryEntitiesCallback, ) -> None: coordinator = entry.runtime_data async_add_entities([NinstripSacnUniverse(coordinator), NinstripSacnStartSlot(coordinator)]) class NinstripSacnUniverse(NinstripSacnEntity, NumberEntity): """Das erste Universe. Braucht der Strip mehr, folgen die naechsten.""" _attr_entity_category = EntityCategory.CONFIG _attr_translation_key = "sacn_universe" _attr_native_min_value = 1 _attr_native_max_value = 63_999 _attr_native_step = 1 _attr_mode = NumberMode.BOX def __init__(self, coordinator: NinstripCoordinator) -> None: super().__init__(coordinator, "sacn_universe") @property def native_value(self) -> float | None: value = self.sacn.get("universe") return float(value) if isinstance(value, (int, float)) else None async def async_set_native_value(self, value: float) -> None: await self.coordinator.async_set_sacn(universe=int(value)) class NinstripSacnStartSlot(NinstripSacnEntity, NumberEntity): """Der erste Slot - er gilt in JEDEM belegten Universe, nicht nur im ersten. Anders als bei ninlight, wo eine Lampe ein einzelner Slotsatz ist: ein Strip verteilt sich ueber mehrere Universes, und in jedem beginnt er an derselben Stelle. """ _attr_entity_category = EntityCategory.CONFIG _attr_translation_key = "sacn_start_slot" _attr_native_min_value = 1 _attr_native_step = 1 _attr_mode = NumberMode.BOX def __init__(self, coordinator: NinstripCoordinator) -> None: super().__init__(coordinator, "sacn_start_slot") @property def native_max_value(self) -> float: """Der hoechste Startslot, hinter dem noch ein ganzes Pixel Platz hat. Bei drei Kanaelen sind das 510. Ein festes 512 wuerde Werte anbieten, bei denen kein einziges Pixel mehr ins Universe passt. """ kanaele = self.sacn.get("channels_per_pixel") if not isinstance(kanaele, int) or not 1 <= kanaele <= 512: kanaele = _KANAELE_VORGABE return 513 - kanaele @property def native_value(self) -> float | None: value = self.sacn.get("start_slot") return float(value) if isinstance(value, (int, float)) else None async def async_set_native_value(self, value: float) -> None: await self.coordinator.async_set_sacn(start_slot=int(value))