import logging from colorsys import hsv_to_rgb from dataclasses import dataclass from random import randint from jinja2 import Environment from lifxlan import LifxLAN from litestar import Litestar, get, post from litestar.contrib.jinja import JinjaTemplateEngine from litestar.response import Template from litestar.template import TemplateConfig logging.basicConfig(level=logging.DEBUG) log = logging.getLogger() # FIXME: discovery happens here, but things can change. # Try power cycling the light and see what happens. lifxlan = LifxLAN() DEFAULT_COLOR = "#FF0000" TEMPLATE_STR = """ lux

{{ message }}

""" @dataclass class RGBColor: red: int green: int blue: int @property def hex(self) -> str: return "#%02x%02x%02x" % (self.red, self.green, self.blue) @property def yit(self) -> int: yit = ((self.red * 299) + (self.green * 587) + (self.blue * 114)) // 1000 log.info(f"yit: {yit}") return yit def __str__(self) -> str: return f"RGBColor(red={self.red}, green={self.green}, blue={self.blue})" @dataclass class HSBKColor: hue: int saturation: int brightness: int kelvin: int @property def rgb(self) -> RGBColor: r, g, b = hsv_to_rgb( self.hue / 65535, self.saturation / 65535, self.brightness / 65535 ) return RGBColor(red=int(r * 255), green=int(g * 255), blue=int(b * 255)) def __str__(self) -> str: return f"HSBKColor(hue={self.hue}, saturation={self.saturation}, brightness={self.brightness}, kelvin={self.kelvin})" def get_random_hsbk_color() -> HSBKColor: return HSBKColor( hue=randint(0, 65535), saturation=randint(0, 65535), brightness=randint(0, 65535), kelvin=randint(0, 9000), ) def random_light() -> Template: hsbk = get_random_hsbk_color() log.info(f"Setting color to {hsbk} {hsbk.rgb}") try: # colors = lifxlan.get_color_all_lights() lifxlan.set_color_all_lights( [hsbk.hue, hsbk.saturation, hsbk.brightness, hsbk.kelvin], rapid=True, ) except Exception as e: log.exception("Error setting color") return Template( template_str=TEMPLATE_STR, context={"color": DEFAULT_COLOR, "message": f"error: {str(e)}"}, ) rgb = hsbk.rgb rgb_hex = rgb.hex text_color = "black" if rgb.yit >= 128 else "white" return Template( template_str=TEMPLATE_STR, context={ "background_color": rgb_hex, "color": text_color, "message": rgb_hex, }, ) @get("/") async def get_index() -> Template: """Return index""" return random_light() @post("/") async def post_index() -> Template: """Update index""" return random_light() # @post("/") # async def post_index( # hue: int, saturation: int, brightness: int, kelvin: int # ) -> dict[str, str]: # try: # lifxlan.set_color_all_lights( # [hue, saturation, brightness, kelvin], # rapid=True, # ) # except Exception as e: # return {"status": "error", "message": str(e)} # return {"status": "ok"} app = Litestar( [ get_index, post_index, ], template_config=TemplateConfig( instance=JinjaTemplateEngine.from_environment(Environment()) ), )