From 4d4e1b83f175f1bcb35e4cbb02353247a47a8c40 Mon Sep 17 00:00:00 2001 From: Morgana Date: Wed, 7 Oct 2026 17:40:23 -0500 Subject: Add lighting management --- app.py | 86 ++++++++++++++++++++++++++++++++++++++++++++------- static/style/mgmt.css | 37 ++++++++++++++++++++++ templates/index.html | 1 + templates/login.html | 4 +-- templates/mgmt.html | 39 +++++++++++++++++++++++ 5 files changed, 153 insertions(+), 14 deletions(-) create mode 100644 static/style/mgmt.css create mode 100644 templates/mgmt.html diff --git a/app.py b/app.py index 484656c..4bd5d3f 100644 --- a/app.py +++ b/app.py @@ -3,6 +3,7 @@ from hashlib import scrypt from os import urandom from hmac import compare_digest import sqlite3 +from colorsys import rgb_to_hsv from flask import ( Flask, @@ -14,7 +15,8 @@ from flask import ( g, flash, ) -from werkzeug.exceptions import HTTPException, NotImplemented +from werkzeug.exceptions import HTTPException, NotImplemented, BadRequest +import requests from captcha import Captcha from presets import GUEST_CAPTCHA, GUIDE_CAPTCHAS @@ -123,6 +125,19 @@ def index(): return render_template("index.html", news=results) +@app.route("/captcha") +def captcha(): + size = request.args.get("size", "") + label = request.args.get("label", "") + lock = request.args.get("lock", "") + answer = request.args.get("answer", "") + captcha = Captcha.safe_validate(size, label, lock, answer) + if captcha: + add_captcha(captcha.id) + return {"valid": True}, 200 + return {"valid": False}, 400 + + @app.route("/login", methods=["GET", "POST"]) def login(): db = get_db() @@ -206,17 +221,64 @@ def news(): return render_template("news.html", news=results) -@app.route("/captcha") -def captcha(): - size = request.args.get("size", "") - label = request.args.get("label", "") - lock = request.args.get("lock", "") - answer = request.args.get("answer", "") - captcha = Captcha.safe_validate(size, label, lock, answer) - if captcha: - add_captcha(captcha.id) - return {"valid": True}, 200 - return {"valid": False}, 400 +@app.route("/mgmt", methods=["GET", "POST"]) +def management(): + if request.method == "POST": + try: + lid_key = request.form.get("lid", "custom") + if lid_key == "custom": + lid = int(request.form.get("custom", "5")) + else: + lid = int(lid_key) + except ValueError: + raise BadRequest + set_key = request.form.get("set") + match set_key: + case "off": + tool_disable_light(lid) + case "on": + tool_enable_light(lid) + case "color": + tool_color_light(lid, request.form.get("color", "#FF00AA")) + case _: + raise BadRequest + return render_template("mgmt.html") + + +def tool_disable_light(light: int): + requests.put( + f"{LIGHT_URL}/lights/{light}/state", + json={"on": False}, + timeout=5, + ) + + +def tool_enable_light(light: int): + requests.put( + f"{LIGHT_URL}/lights/{light}/state", + json={"on": True, "ct": 366}, + timeout=5, + ) + + +def tool_color_light(light: int, color: str): + if color[0] == "#": + color = color[1:] + color = color.upper() + if len(color) != 6 or not all(c in HEX_CHARS for c in color): + color = "FF00AA" + rgb = [int(color[i : i + 2], 16) / 255 for i in range(0, 6, 2)] + hsv = rgb_to_hsv(*rgb) + requests.put( + f"{LIGHT_URL}/lights/{light}/state", + json={ + "on": True, + "hue": int(hsv[0] * 65535), + "sat": int(hsv[1] * 254), + "bri": int(hsv[2] * 254), + }, + timeout=5, + ) @app.route("/permits") diff --git a/static/style/mgmt.css b/static/style/mgmt.css new file mode 100644 index 0000000..9ec93ef --- /dev/null +++ b/static/style/mgmt.css @@ -0,0 +1,37 @@ +h3 { + display: inline; + font-size: inherit; +} + +form { + display: grid; + grid-template-columns: auto 1fr; + gap: 0.5em; + margin: 0.5em; +} + +label[for="light"], +label[for="color"], +input[type="radio"] { + align-content: center; + justify-self: end; +} + +input[type="color"] { + padding: 0; + height: 2em; +} + +button { + grid-column: 1 / span 2; + border: 1px solid black; +} + +hr { + grid-column: 1 / span 2; + width: 100%; +} + +input { + border: 1px solid black; +} \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index 8126ae1..ad884cf 100644 --- a/templates/index.html +++ b/templates/index.html @@ -24,6 +24,7 @@