feat(light): Farbe und Farbtemperatur ueber alle Segmente
In Home Assistant liessen sich nur Szenen und Helligkeit stellen, keine Farben - device/state traegt naemlich keine. Die steht je Segment, und die Segmente hat der Koordinator bisher gar nicht gelesen. Jetzt holt er device/segments mit (fuenfte Anfrage je Zyklus), und die Lichtentitaet bietet rgb_color und color_temp_kelvin an: * Setzen schreibt in ALLE Segmente, aber nur die Farbfelder - Grenzen, Namen und Helligkeit bleiben stehen. Die Einteilung eines Strips ist von Hand gemacht, die reisst eine Farbwahl nicht ein. Geschrieben wird die ganze Liste auf einmal, danach zurueckgelesen statt angenommen. * Angezeigt wird nur, worauf sich alle Segmente einigen. Zwei Farben und eine Entitaet - da waere jede Angabe gelogen, also gibt es keine. * Farbtemperatur nur, wenn alle auf "white" stehen; sonst RGB, sonst blendete HA den Farbkreis aus, sobald ein Segment einen Effekt faehrt. * Die Farbe geht VOR dem Einschalten raus, sonst leuchtet der Strip kurz in der alten auf. Die Spanne 2700-6500 K ist die, die die Firmware auf die Weisskanaele umrechnet (nl_ct.h); ohne Weisskanaele naehert sie sie in RGB an. Dazu: das Markenbild ist jetzt dasselbe wie bei ninlight - Michaels Wunsch, die beiden Integrationen gehoeren zusammen. Das Skript fuer ein eigenes Motiv bleibt als Ausgangspunkt liegen.
This commit is contained in:
@@ -35,6 +35,10 @@ class NinstripData:
|
||||
state: dict[str, Any]
|
||||
info: dict[str, Any]
|
||||
presets: dict[str, Any]
|
||||
# Farbe und Farbtemperatur stehen NICHT in device/state, sondern je
|
||||
# Segment. Ohne diese Liste koennte die Lichtentitaet keine Farbe zeigen
|
||||
# und keine setzen.
|
||||
segments: dict[str, Any]
|
||||
# Nur, was das Geraet unter system/settings zeigt. Aeltere Firmware traegt
|
||||
# dort keinen sacn-Block - die Entitaeten melden sich dann nicht
|
||||
# verfuegbar, statt zu verschwinden.
|
||||
@@ -85,6 +89,7 @@ class NinstripCoordinator(DataUpdateCoordinator[NinstripData]):
|
||||
state = await self.client.get_state()
|
||||
info = await self.client.get_info()
|
||||
presets = await self.client.get_presets()
|
||||
segments = await self.client.get_segments()
|
||||
# Die sACN-Einstellungen liegen hinter system/settings, nicht in
|
||||
# device/state - eine vierte Anfrage je Zyklus. Wie ha-ninlight.
|
||||
settings = await self.client.get_settings()
|
||||
@@ -103,7 +108,7 @@ class NinstripCoordinator(DataUpdateCoordinator[NinstripData]):
|
||||
return self.data
|
||||
raise UpdateFailed(f"{self.client.host}: {err}") from err
|
||||
self._consecutive_poll_failures = 0
|
||||
return NinstripData(state, info, presets, settings)
|
||||
return NinstripData(state, info, presets, segments, settings)
|
||||
|
||||
async def async_call[T](self, action: Callable[[NinstripClient], Awaitable[T]]) -> T:
|
||||
"""Fuehrt eine Anfrage unter der Sperre aus und uebersetzt Fehler fuer die Oberflaeche."""
|
||||
@@ -135,7 +140,9 @@ class NinstripCoordinator(DataUpdateCoordinator[NinstripData]):
|
||||
state = await self.async_call(lambda client: client.set_state(**fields))
|
||||
self._consecutive_poll_failures = 0
|
||||
self.async_set_updated_data(
|
||||
NinstripData(state, self.data.info, self.data.presets, self.data.settings)
|
||||
NinstripData(
|
||||
state, self.data.info, self.data.presets, self.data.segments, self.data.settings
|
||||
)
|
||||
)
|
||||
|
||||
async def async_set_sacn(self, **fields: Any) -> None:
|
||||
@@ -154,7 +161,43 @@ class NinstripCoordinator(DataUpdateCoordinator[NinstripData]):
|
||||
settings = await self.async_call(schreiben_und_lesen)
|
||||
self._consecutive_poll_failures = 0
|
||||
self.async_set_updated_data(
|
||||
NinstripData(self.data.state, self.data.info, self.data.presets, settings)
|
||||
NinstripData(
|
||||
self.data.state,
|
||||
self.data.info,
|
||||
self.data.presets,
|
||||
self.data.segments,
|
||||
settings,
|
||||
)
|
||||
)
|
||||
|
||||
async def async_set_all_segments(self, **fields: Any) -> None:
|
||||
"""Schreibt dieselben Felder in JEDES Segment und liest zurueck.
|
||||
|
||||
Die Grenzen und Namen der Segmente bleiben dabei stehen - gesetzt wird
|
||||
nur, was uebergeben wird. Eine Farbe ueber die Lichtentitaet soll die
|
||||
muehsam von Hand gemachte Einteilung des Strips nicht einreissen.
|
||||
|
||||
Geschrieben wird die ganze Liste auf einmal: das Geraet nimmt sie als
|
||||
Ganzes an oder gar nicht, und es ist eine Anfrage statt einer je
|
||||
Segment. Danach wird zurueckgelesen statt angenommen, wie bei sACN.
|
||||
"""
|
||||
|
||||
async def schreiben_und_lesen(client: NinstripClient) -> dict[str, Any]:
|
||||
alt = self.data.segments.get("segments") or []
|
||||
neu = [{**seg, **fields} for seg in alt]
|
||||
await client.put_segments(neu)
|
||||
return await client.get_segments()
|
||||
|
||||
segments = await self.async_call(schreiben_und_lesen)
|
||||
self._consecutive_poll_failures = 0
|
||||
self.async_set_updated_data(
|
||||
NinstripData(
|
||||
self.data.state,
|
||||
self.data.info,
|
||||
self.data.presets,
|
||||
segments,
|
||||
self.data.settings,
|
||||
)
|
||||
)
|
||||
|
||||
async def async_after_change(self) -> None:
|
||||
|
||||
Reference in New Issue
Block a user