Improve color parsing

This commit is contained in:
Torjus Håkestad 2024-06-15 11:29:22 +02:00
parent aa23ddcffa
commit 00ab4ab6b3
2 changed files with 36 additions and 15 deletions

View File

@ -1,5 +1,6 @@
import os
from enum import Enum
from typing import NamedTuple
from typing_extensions import Annotated
import typer
import json
@ -10,6 +11,10 @@ class LightState(str, Enum):
on = "off"
off = "on"
class XYColor(NamedTuple):
x: float
y: float
NAME_TO_ID = {
"bedroom": "0x001788010d1b599a",
@ -70,7 +75,7 @@ def complete_state(incomplete: str):
return completion
def rgb_to_xy(red, green, blue):
def rgb_to_xy(red, green, blue) -> XYColor:
"""conversion of RGB colors to CIE1931 XY colors
Formulas implemented from: https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d
@ -105,7 +110,7 @@ def rgb_to_xy(red, green, blue):
# TODO check color gamut if known
return [x, y]
return XYColor(x, y)
app = typer.Typer()
@ -126,17 +131,12 @@ def set_color(
"""
str_id = NAME_TO_ID[id]
topic = f"zigbee2mqtt/{str_id}/set"
if color in COLOR_MAP:
payload_raw = {
"color": {"x": COLOR_MAP[color][0], "y": COLOR_MAP[color][1]},
"color_mode": "xy",
}
payload = json.dumps(payload_raw)
else:
c = color.split(",")
xy = rgb_to_xy(float(c[0]), float(c[1]), float(c[2]))
raw_payload = {"x": xy[0], "y": xy[1]}
payload = json.dumps(raw_payload)
xy = parse_color(color)
payload_raw= {
"color": {"x": xy[0], "y": xy[1]},
"color_mode": "xy",
}
payload = json.dumps(payload_raw)
pub.single(topic, payload, hostname=get_mqtt_broker())
@ -173,6 +173,27 @@ def set_brightness(
payload = json.dumps({"brightness": brightness})
pub.single(topic, payload, hostname=get_mqtt_broker())
def parse_color(color: str) -> XYColor:
if color in COLOR_MAP:
return XYColor(COLOR_MAP[color][0], COLOR_MAP[color][1])
split = color.split(",")
match len(split):
case 2:
return XYColor(float(split[0]), float(split[1]))
case 3:
return _parse_rgb_color(float(split[0]), float(split[1]), float(split[2]))
case _:
raise ValueError("Invalid color format")
def _parse_rgb_color(r: float, g: float, b: float) -> XYColor:
if any(val > 1 for val in [r,g,b]):
if any(val > 255 for val in [r,g,b]):
raise ValueError("RGB values must be between 0 and 255 or 0.0 and 1.0")
vals = [val/255 for val in [r,g,b]]
return rgb_to_xy(vals[0], vals[1], vals[2])
if all(val > 0 and val < 1 for val in [r,g,b]):
return rgb_to_xy(r,g,b)
raise ValueError("RGB values must be between 0 and 255 or 0.0 and 1.0")
def main():
app()

View File

@ -1,7 +1,7 @@
[tool.poetry]
name = "huecli"
version = "0.1.0"
description = ""
version = "0.1.1"
description = "Set Philips Hue lights using MQTT"
authors = ["Torjus Håkestad <torjus@uio.no>"]
license = "MIT"
readme = "README.md"