Implemented basic device controls
This commit is contained in:
parent
aca30088b0
commit
aefa4275d4
2 changed files with 214 additions and 132 deletions
233
app.py
233
app.py
|
@ -1,34 +1,20 @@
|
|||
from __future__ import annotations
|
||||
from contextlib import asynccontextmanager
|
||||
from nt import device_encoding
|
||||
from typing import Annotated
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
from sqlmodel import SQLModel, Session, col, create_engine, select
|
||||
from netbrite import NetBrite, NetbriteConnectionException, Zone
|
||||
from sqlmodel import SQLModel, Session, create_engine, delete, select
|
||||
|
||||
import netbrite as nb
|
||||
from db import (
|
||||
APIAddNetBriteDevice,
|
||||
APIGetNetBriteDevice,
|
||||
APIGetZone,
|
||||
APIMessages,
|
||||
BaseNetBriteDevice,
|
||||
BaseZone,
|
||||
MessageDB,
|
||||
NetBriteBase,
|
||||
NetBriteDB,
|
||||
NetBritePublic,
|
||||
ZoneDB,
|
||||
)
|
||||
|
||||
sqlite_file_name = "devices.db"
|
||||
sqlite_url = f"sqlite:///{sqlite_file_name}"
|
||||
|
||||
connect_args = {"check_same_thread": False}
|
||||
engine = create_engine(sqlite_url, connect_args=connect_args)
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
print("creating tables")
|
||||
create_db_and_tables()
|
||||
yield
|
||||
|
||||
|
||||
def create_db_and_tables():
|
||||
SQLModel.metadata.create_all(engine)
|
||||
DB_URL = "sqlite:///devices.db"
|
||||
engine = create_engine(DB_URL, connect_args={"check_same_thread": False})
|
||||
|
||||
|
||||
def get_session():
|
||||
|
@ -38,78 +24,161 @@ def get_session():
|
|||
|
||||
SessionDep = Annotated[Session, Depends(get_session)]
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(_: FastAPI):
|
||||
SQLModel.metadata.create_all(engine)
|
||||
load_devices_from_db()
|
||||
yield
|
||||
|
||||
|
||||
app = FastAPI(lifespan=lifespan)
|
||||
devices: list[NetBrite] = []
|
||||
|
||||
active_devices: dict[int, nb.NetBrite] = {}
|
||||
device_status: dict[int, bool] = {}
|
||||
|
||||
|
||||
@app.post("/api/device")
|
||||
def create_device(device: APIAddNetBriteDevice, session: SessionDep):
|
||||
statement = select(BaseNetBriteDevice).where(
|
||||
col(BaseNetBriteDevice.address) == device.address
|
||||
)
|
||||
result = session.exec(statement)
|
||||
if result.first() != None:
|
||||
raise HTTPException(400, "Device is already added")
|
||||
# ---------- 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:
|
||||
netbrite_device = NetBrite(device.address, device.port)
|
||||
devices.append(netbrite_device)
|
||||
except NetbriteConnectionException as exc:
|
||||
raise HTTPException(400, "Failed to connect to device")
|
||||
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)
|
||||
|
||||
dbdevice = BaseNetBriteDevice(address=device.address, port=device.port)
|
||||
session.add(dbdevice)
|
||||
session.commit()
|
||||
session.refresh(dbdevice)
|
||||
|
||||
return device
|
||||
return 200
|
||||
|
||||
|
||||
@app.get("/api/devices")
|
||||
def get_devices(session: SessionDep):
|
||||
db_devices: dict[int, BaseNetBriteDevice] = {}
|
||||
|
||||
statement = select(BaseZone, BaseNetBriteDevice).join(BaseNetBriteDevice)
|
||||
results = session.exec(statement)
|
||||
|
||||
for zone, device in results:
|
||||
if device.id == None:
|
||||
continue
|
||||
if not device.id in db_devices:
|
||||
connected = devices.inde
|
||||
get_device = APIGetNetBriteDevice(device., zones={})
|
||||
db_devices[device.id] = device
|
||||
|
||||
db_devices[device.id].zones_list
|
||||
# ---------- helper ----------
|
||||
def load_devices_from_db() -> None:
|
||||
with Session(engine) as session:
|
||||
for device in session.exec(select(NetBriteDB)).all():
|
||||
load_device(device, session)
|
||||
|
||||
|
||||
for device in devices:
|
||||
def load_device(device: NetBriteDB, session: SessionDep):
|
||||
id = device.id or 0
|
||||
try:
|
||||
active_devices[id] = nb.NetBrite(device.address, device.port)
|
||||
device_status[id] = True
|
||||
load_zones(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}")
|
||||
|
||||
zones: dict[str, APIGetZone] = {}
|
||||
for index, zone in device.zones_list.items():
|
||||
x, y, xend, yend = zone.rect
|
||||
width = xend - x
|
||||
height = yend - y
|
||||
|
||||
zones[index] = APIGetZone(
|
||||
x=x,
|
||||
y=y,
|
||||
width=width,
|
||||
height=height,
|
||||
scroll_speed=zone.scroll_speed,
|
||||
pause_duration=zone.pause_duration,
|
||||
volume=zone.volume,
|
||||
default_font=zone.default_font,
|
||||
default_color=zone.default_color,
|
||||
default_message=zone.initial_text,
|
||||
def load_zones(session: Session, device_id: int, net_dev: nb.NetBrite) -> None:
|
||||
zones: dict[str, nb.Zone] = {}
|
||||
statement = select(ZoneDB).where(ZoneDB.netbrite_id == device_id)
|
||||
|
||||
for zone in session.exec(statement).all():
|
||||
msg = zone.default_message
|
||||
|
||||
default_msg = (
|
||||
nb.Message(
|
||||
text=msg.text,
|
||||
)
|
||||
if msg
|
||||
else nb.Message(f"Zone {zone.name}")
|
||||
)
|
||||
|
||||
return devices
|
||||
zones[zone.name] = nb.Zone(
|
||||
x=zone.x,
|
||||
y=zone.y,
|
||||
width=zone.width,
|
||||
height=zone.height,
|
||||
scroll_speed=zone.scroll_speed,
|
||||
pause_duration=zone.pause_duration,
|
||||
volume=zone.volume,
|
||||
default_font=zone.default_font,
|
||||
default_color=zone.default_color,
|
||||
initial_text=default_msg,
|
||||
)
|
||||
|
||||
if zones:
|
||||
net_dev.zones(zones)
|
||||
|
||||
|
||||
@app.get("/api/devices/{device_index}")
|
||||
def get_device(device_index: int):
|
||||
if device_index > len(devices) - 1:
|
||||
raise HTTPException(400, "Device doesn't exist")
|
||||
def create_default_zone(session: Session, device_id: int) -> None:
|
||||
zone = ZoneDB(
|
||||
name="0",
|
||||
x=0,
|
||||
y=0,
|
||||
width=150,
|
||||
height=7,
|
||||
netbrite_id=device_id,
|
||||
)
|
||||
msg = MessageDB(
|
||||
text="{erase}Welcome",
|
||||
ttl=60,
|
||||
)
|
||||
session.add(msg)
|
||||
session.add(zone)
|
||||
|
||||
return devices[device_index]
|
||||
session.commit()
|
||||
session.refresh(zone)
|
||||
session.refresh(msg)
|
||||
|
||||
zone.default_message_id = msg.id
|
||||
session.commit()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue