Mercurial > code > home > repos > light-bridge
view light.py @ 19:4e350dcdc4fe
zero button
author | drewp@bigasterisk.com |
---|---|
date | Mon, 29 Jan 2024 11:50:28 -0800 |
parents | 1d15dc4d673f |
children | 24a574108365 |
line wrap: on
line source
import asyncio import logging from dataclasses import dataclass from typing import Callable from color import Color from color_convert import DeviceColor, zbConv from mqtt_io import MqttIo from protocols import Transport, ZigbeeTransport log = logging.getLogger('light') @dataclass class Light: name: str transport: Transport convertColor: Callable[[Color], DeviceColor] requestingColor: Color = Color.fromHex('#000000') requestingDeviceColor: DeviceColor = DeviceColor() emittingColor: Color = Color.fromHex('#000000') online: bool | None = None latencyMs: float | None = None notifyChanged: Callable | None = None def __post_init__(self): self.requestingDeviceColor = self.convertColor(self.requestingColor) def to_dict(self): d = { 'name': self.name, 'address': self.transport.linked(), 'requestingColor': self.requestingColor.hex(), 'requestingDeviceColor': self.requestingDeviceColor.summary(), 'emittingColor': self.emittingColor.hex(), 'online': self.online, 'latencyMs': self.latencyMs, } return {'light': d} async def setColor(self, c: Color): log.info(f'setColor from {self.requestingColor} to {c}') if c == self.requestingColor: return self.requestingColor = c self.requestingDeviceColor = self.convertColor(self.requestingColor) if self.notifyChanged: self.notifyChanged() # waits for the relevant round-trip log.info(f'transport send {self.requestingDeviceColor.summary()}') await self.transport.send(self.requestingDeviceColor) self.emittingColor = self.requestingColor if self.notifyChanged: self.notifyChanged() def makeZbBar(mqtt: MqttIo, name: str, ieee: str) -> Light: return Light(name=name, convertColor=zbConv, transport=ZigbeeTransport(mqtt, name, ieee)) class Lights: _d: dict[str, Light] = {} def __init__(self, mqtt: MqttIo): self.mqtt = mqtt self.add(makeZbBar(mqtt, 'do-bar', '0xa4c13844948d2da4')) def add(self, d: Light): d.notifyChanged = self.notifyChanged self._d[d.name] = d self.notifyChanged() def byName(self, name: str) -> Light: return self._d[name] def to_dict(self): return {'lights': [d.to_dict() for d in sorted(self._d.values(), key=lambda r: r.name)]} # the following is bad. Get a better events lib. _changeSleepTask: asyncio.Task | None = None async def changes(self): # yields None on any data change while True: log.info('Lights has a change') yield None self._changeSleepTask = asyncio.create_task(self._sleep()) try: await self._changeSleepTask except asyncio.CancelledError: pass self._changeSleepTask = None async def _sleep(self): await asyncio.sleep(100) def notifyChanged(self): log.info('Lights.notifyChanged()') if self._changeSleepTask is not None: self._changeSleepTask.cancel()