From 33715cb34e821697bc06f07ceffa7a4858a2d5de Mon Sep 17 00:00:00 2001 From: Jurn Wubben Date: Tue, 26 Aug 2025 16:32:08 +0200 Subject: [PATCH] cleaned up and added some extra routes for zones --- app.py | 232 ++++++++++++++++++++++++++++++++++++++------------------- db.py | 3 +- 2 files changed, 155 insertions(+), 80 deletions(-) diff --git a/app.py b/app.py index f74fd08..5edce19 100644 --- a/app.py +++ b/app.py @@ -10,7 +10,9 @@ from db import ( NetBriteBase, NetBriteDB, NetBritePublic, + ZoneBase, ZoneDB, + ZonePublic, ) DB_URL = "sqlite:///devices.db" @@ -38,78 +40,6 @@ active_devices: dict[int, nb.NetBrite] = {} device_status: dict[int, bool] = {} -# ---------- routes ---------- -@app.post("/api/device", response_model=NetBritePublic) -def create_device(device: NetBriteBase, session: SessionDep): - if session.exec( - select(NetBriteDB).where(NetBriteDB.address == device.address) - ).first(): - raise HTTPException(400, "Device already exists") - - db_device = NetBriteDB.model_validate(device) - session.add(db_device) - session.commit() - session.refresh(db_device) - - load_device(db_device, session) - return db_device - - -@app.get("/api/devices", response_model=list[NetBritePublic]) -def get_devices(session: SessionDep): - return session.exec(select(NetBriteDB)).all() - - -@app.post("/api/devices/{device_id}", response_model=NetBritePublic) -def update_device(device_id: int, session: SessionDep): - db_dev = session.get(NetBriteDB, device_id) - if not db_dev: - raise HTTPException(404, "Device not found") - - return db_dev - - -# TODO: implement me -@app.post("/api/devices/{device_id}/reconnect") -def connect_device(device_id: int, session: SessionDep) -> dict[str, bool]: - db_dev = session.get(NetBriteDB, device_id) - if not db_dev: - raise HTTPException(404, "Device not found") - - try: - active_devices[device_id] = nb.NetBrite(db_dev.address, db_dev.port) - device_status[device_id] = True - load_zones(session, device_id, active_devices[device_id]) - return {"connected": True} - except nb.NetbriteConnectionException as exc: - device_status[device_id] = False - raise HTTPException(400, str(exc)) - - -@app.delete("/api/devices/{device_id}") -def delete_device(device_id: int, session: SessionDep): - db_dev = session.get(NetBriteDB, device_id) - if not db_dev: - raise HTTPException(404, "Device not found") - - delete: list[MessageDB | ZoneDB | NetBriteDB] = [db_dev] - for zone in db_dev.zones: - if zone.default_message != None: - delete.append(zone.default_message) - delete.append(zone) - - if device_id in active_devices: - active_devices[device_id].sock.close() - del active_devices[device_id] - - print(delete) - for i in delete: - session.delete(i) - - session.commit() - return 200 - - # ---------- helper ---------- def load_devices_from_db() -> None: with Session(engine) as session: @@ -122,22 +52,31 @@ def load_device(device: NetBriteDB, session: SessionDep): try: active_devices[id] = nb.NetBrite(device.address, device.port) device_status[id] = True - load_zones(session, id, active_devices[id]) + load_zones_id(session, id, active_devices[id]) except nb.NetbriteConnectionException as exc: device_status[id] = False print(f"Could not connect to {device.address}:{device.port} — {exc}") -def load_zones(session: Session, device_id: int, net_dev: nb.NetBrite) -> None: - zones: dict[str, nb.Zone] = {} +def load_zones_id(session: Session, device_id: int, net_dev: nb.NetBrite): statement = select(ZoneDB).where(ZoneDB.netbrite_id == device_id) + zones = list(session.exec(statement)) + load_zones(zones, net_dev) - for zone in session.exec(statement).all(): + +def load_zones(zones_in: list[ZoneDB], net_dev: nb.NetBrite) -> None: + zones: dict[str, nb.Zone] = {} + + for zone in zones_in: msg = zone.default_message default_msg = ( nb.Message( + activation_delay=msg.activation_delay, + display_delay=msg.display_delay, + priority=msg.priority, text=msg.text, + ttl=msg.ttl, ) if msg else nb.Message(f"Zone {zone.name}") @@ -165,13 +104,12 @@ def create_default_zone(session: Session, device_id: int) -> None: name="0", x=0, y=0, - width=150, + width=120, height=7, netbrite_id=device_id, ) msg = MessageDB( text="{erase}Welcome", - ttl=60, ) session.add(msg) session.add(zone) @@ -182,3 +120,141 @@ def create_default_zone(session: Session, device_id: int) -> None: zone.default_message_id = msg.id session.commit() + + +# ---------- routes ---------- +@app.post("/api/device", response_model=NetBritePublic) +def create_device(device: NetBriteBase, session: SessionDep): + if session.exec( + select(NetBriteDB).where(NetBriteDB.address == device.address) + ).first(): + raise HTTPException(400, "Device already exists") + + db_device = NetBriteDB.model_validate(device) + session.add(db_device) + session.commit() + session.refresh(db_device) + + load_device(db_device, session) + return db_device + + +@app.get("/api/devices", response_model=list[NetBritePublic]) +def get_devices(session: SessionDep): + devices: list[NetBritePublic] = [] + + for device in session.exec(select(NetBriteDB)).all(): + device = NetBritePublic.model_validate( + device, update={"active": device_status.get(device.id or 0) or False} + ) + devices.append(device) + + return devices # FIXME: implement active + + +@app.post("/api/devices/{device_id}", response_model=NetBritePublic) +def update_device(device_id: int, updated_device: NetBriteBase, session: SessionDep): + db_dev = session.get(NetBriteDB, device_id) + if not db_dev: + raise HTTPException(404, "Device not found") + + db_dev.port = updated_device.port + db_dev.address = updated_device.address + + return 200 + + +# TODO: implement me +@app.post("/api/devices/{device_id}/reconnect") +def reconnect_device(device_id: int, session: SessionDep): + db_dev = session.get(NetBriteDB, device_id) + if not db_dev: + raise HTTPException(404, "Device not found") + + try: + active_devices[device_id] = nb.NetBrite(db_dev.address, db_dev.port) + device_status[device_id] = True + load_zones_id(session, device_id, active_devices[device_id]) + return 200 + except nb.NetbriteConnectionException as exc: + device_status[device_id] = False + raise HTTPException(400, str(exc)) + + +@app.delete("/api/devices/{device_id}") +def delete_device(device_id: int, session: SessionDep): + db_dev = session.get(NetBriteDB, device_id) + if not db_dev: + raise HTTPException(404, "Device not found") + + delete: list[MessageDB | ZoneDB | NetBriteDB] = [db_dev] + for zone in db_dev.zones: + if zone.default_message != None: + delete.append(zone.default_message) + delete.append(zone) + + if device_id in active_devices: + active_devices[device_id].sock.close() + del active_devices[device_id] + + for i in delete: + session.delete(i) + + session.commit() + return 200 + + +@app.post("/api/devices/{device_id}/zones", response_model=ZonePublic) +def create_zone(device_id: int, body: ZoneBase, session: SessionDep): + device = session.get(NetBriteDB, device_id) + if not device: + raise HTTPException(404, "Device not found") + + zone = ZoneDB.model_validate(body) + msg = MessageDB( + text="{erase}Welcome", + ) + session.add(zone) + session.add(msg) + + session.commit() + session.refresh(zone) + session.refresh(msg) + + zone.default_message_id = msg.id + session.commit() + + if not device.id in active_devices: + raise HTTPException(503, "Device not active") + + try: + load_zones(device.zones, active_devices[device.id]) + except nb.NetbriteTransferException: + raise HTTPException(503, "Device not active") + + +@app.get("/api/devices/{device_id}/zones", response_model=list[ZonePublic]) +def get_zones(device_id: int, session: SessionDep): + device = session.get(NetBriteDB, device_id) + if not device: + raise HTTPException(404, "Device not found") + + return device.zones + + +@app.delete( + "/api/zone/{zone_id}", +) +def delete_zone(zone_id: int, session: SessionDep): + zone = session.get(ZoneDB, zone_id) + if not zone: + raise HTTPException(404, "Zone not found") + + message = zone.default_message + if message: + session.delete(message) + + session.delete(zone) + session.commit() + + return 200 diff --git a/db.py b/db.py index 0370419..a62f3f6 100644 --- a/db.py +++ b/db.py @@ -22,7 +22,6 @@ class MessageDB(MessageBase, table=True): class MessagePublic(MessageBase): id: int - zone: "ZoneDB" # --- Device --- @@ -75,4 +74,4 @@ class ZoneDB(ZoneBase, table=True): class ZonePublic(ZoneBase): id: int default_message: MessagePublic - netbrite: NetBritePublic + # netbrite: NetBritePublic