| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -12,6 +12,7 @@ class LightState(str, Enum):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    on = "off"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    off = "on"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				class XYColor(NamedTuple):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    x: float
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    y: float
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -45,6 +46,7 @@ class LightID(str, Enum):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    all = "all"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    infuse = "infuse"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def get_mqtt_broker():
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if "HUECLI_BROKER" in os.environ:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return os.environ["HUECLI_BROKER"]
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -67,6 +69,7 @@ def complete_id(incomplete: str):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            completion.append(id)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return completion
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def complete_state(incomplete: str):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    states = ["on", "off"]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    completion = []
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -133,7 +136,7 @@ def set_color(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    str_id = NAME_TO_ID[id]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    topic = f"zigbee2mqtt/{str_id}/set"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    xy = parse_color(color)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    payload_raw= {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    payload_raw = {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        "color": {"x": xy[0], "y": xy[1]},
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        "color_mode": "xy",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -143,12 +146,14 @@ def set_color(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				@app.command()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def set_state(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        id: Annotated[
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LightID, typer.Argument(help="ID of light.", autocompletion=complete_id)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        ],
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        state: Annotated[
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LightState, typer.Argument(help="State of light.", autocompletion=complete_state)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        ]):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    id: Annotated[
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        LightID, typer.Argument(help="ID of light.", autocompletion=complete_id)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    ],
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    state: Annotated[
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        LightState,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        typer.Argument(help="State of light.", autocompletion=complete_state),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    ],
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    """
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    Set the state of ID to STATE
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    """
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -160,10 +165,11 @@ def set_state(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				@app.command()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def set_brightness(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        id: Annotated[
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            LightID, typer.Argument(help="ID of light.", autocompletion=complete_id)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        ],
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        brightness: int):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    id: Annotated[
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        LightID, typer.Argument(help="ID of light.", autocompletion=complete_id)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    ],
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    brightness: int,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    """
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    Set brigthness of ID to BRIGHTNESS
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    """
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -174,6 +180,7 @@ def set_brightness(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    payload = json.dumps({"brightness": brightness})
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    pub.single(topic, payload, hostname=get_mqtt_broker())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				@app.command()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def version():
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    """
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -182,6 +189,7 @@ def version():
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    version = importlib.metadata.version("huecli")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    typer.echo(f"huecli {version}")
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				def parse_color(color: str) -> XYColor:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if color in COLOR_MAP:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return XYColor(COLOR_MAP[color][0], COLOR_MAP[color][1])
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -194,16 +202,18 @@ def parse_color(color: str) -> XYColor:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        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]):
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    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]]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        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)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    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()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				 
 |