Compare commits
	
		
			2 Commits
		
	
	
		
			aa23ddcffa
			...
			5c12b69409
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 5c12b69409 | |||
| 00ab4ab6b3 | 
							
								
								
									
										18
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										18
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							@@ -59,11 +59,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "nixpkgs": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1716948383,
 | 
			
		||||
        "narHash": "sha256-SzDKxseEcHR5KzPXLwsemyTR/kaM9whxeiJohbL04rs=",
 | 
			
		||||
        "lastModified": 1718318537,
 | 
			
		||||
        "narHash": "sha256-4Zu0RYRcAY/VWuu6awwq4opuiD//ahpc2aFHg2CWqFY=",
 | 
			
		||||
        "owner": "NixOS",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "rev": "ad57eef4ef0659193044870c731987a6df5cf56b",
 | 
			
		||||
        "rev": "e9ee548d90ff586a6471b4ae80ae9cfcbceb3420",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -84,11 +84,11 @@
 | 
			
		||||
        "treefmt-nix": "treefmt-nix"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1717171636,
 | 
			
		||||
        "narHash": "sha256-SwqzDI7ddN8SkfJ0moYMRu9iastqI25YAHPpmI2PlYM=",
 | 
			
		||||
        "lastModified": 1718285706,
 | 
			
		||||
        "narHash": "sha256-DScsBM+kZvxOva7QegfdtleebMXh30XPxDQr/1IGKYo=",
 | 
			
		||||
        "owner": "nix-community",
 | 
			
		||||
        "repo": "poetry2nix",
 | 
			
		||||
        "rev": "3bad7d0f33e6fd09205a19aab01e10af532198f9",
 | 
			
		||||
        "rev": "a5be1bbbe0af0266147a88e0ec43b18c722f2bb9",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -156,11 +156,11 @@
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1715940852,
 | 
			
		||||
        "narHash": "sha256-wJqHMg/K6X3JGAE9YLM0LsuKrKb4XiBeVaoeMNlReZg=",
 | 
			
		||||
        "lastModified": 1717850719,
 | 
			
		||||
        "narHash": "sha256-npYqVg+Wk4oxnWrnVG7416fpfrlRhp/lQ6wQ4DHI8YE=",
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "treefmt-nix",
 | 
			
		||||
        "rev": "2fba33a182602b9d49f0b2440513e5ee091d838b",
 | 
			
		||||
        "rev": "4fc1c45a5f50169f9f29f6a98a438fb910b834ed",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
 
 | 
			
		||||
@@ -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()
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user