view light.py @ 9:9f427d8073c3

redo data model; add ui colors
author drewp@bigasterisk.com
date Sun, 28 Jan 2024 16:53:08 -0800
parents fc8ed0efcd72
children 028ed39aa78f
line wrap: on
line source

import asyncio
import logging
from dataclasses import dataclass, field

from color import Color

log = logging.getLogger('light')


@dataclass(frozen=True)
class DeviceColor:
    """neutral representation of the adjusted color that we send to a device"""
    r: float = 0
    g: float = 0
    b: float = 0
    w: float = 0
    x: float = 0
    y: float = 0

    def summary(self) -> dict:
        return dict([(k, round(v, 3)) for k, v in self.__dict__.items() if v > 0])


@dataclass
class Light:
    name: str
    address: str

    requestingColor: Color = Color.fromHex('#000000')
    requestingDeviceColor: DeviceColor = DeviceColor()

    emittingColor: Color = Color.fromHex('#000000')
    online: bool | None = None
    latencyMs: float | None = None

    def __post_init__(self):
        self.requestingDeviceColor = self.deviceColor(self.requestingColor)

    def to_dict(self):
        d = {
            'name': self.name,
            'address': self.address,
            'requestingColor': self.requestingColor.hex(),
            'requestingDeviceColor': self.requestingDeviceColor.summary(),
            'emittingColor': self.emittingColor.hex(),
            'online': self.online,
            'latencyMs': self.latencyMs,
        }

        return {'light': d}

    def deviceColor(self, c: Color) -> DeviceColor:
        # do LUT here
        return DeviceColor(r=c.r, g=c.g, b=c.b)

    async def setColor(self, c: Color):
        self.requestingColor = c
        self.requestingDeviceColor = self.deviceColor(self.requestingColor)


class Lights:
    _d: dict[str, Light] = {}

    def __init__(self):
        self.add(Light('do-desk', 'topic1'))
        self.add(Light('do-desk2', 'topic2'))

    def add(self, d: Light):
        self._d[d.name] = d

    def byName(self, name: str) -> Light:
        return self._d[name]

    async def changes(self):  # yields None on any data change
        while True:
            yield None
            await asyncio.sleep(1)  # todo

    def to_dict(self):
        return {'lights': [d.to_dict() for d in sorted(self._d.values(), key=lambda r: r.name)]}