88 lines
2.9 KiB
Python
88 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
|
|
from flask_sqlalchemy import SQLAlchemy
|
|
from sqlalchemy import UniqueConstraint
|
|
|
|
|
|
db = SQLAlchemy()
|
|
|
|
|
|
class Display(db.Model):
|
|
__tablename__ = "displays"
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
name = db.Column(db.String(120), nullable=False)
|
|
public_id = db.Column(db.String(64), nullable=False, unique=True, index=True)
|
|
last_seen = db.Column(db.DateTime, nullable=True)
|
|
is_online = db.Column(db.Boolean, nullable=False, default=False)
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<Display {self.public_id} online={self.is_online}>"
|
|
|
|
|
|
class Video(db.Model):
|
|
__tablename__ = "videos"
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
filename = db.Column(db.String(255), nullable=False, unique=True)
|
|
duration = db.Column(db.Float, nullable=True) # seconds
|
|
uploaded_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<Video {self.filename}>"
|
|
|
|
|
|
class Event(db.Model):
|
|
__tablename__ = "events"
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
name = db.Column(db.String(120), nullable=False)
|
|
udp_port = db.Column(db.Integer, nullable=True)
|
|
udp_payload = db.Column(db.String(255), nullable=True)
|
|
cooldown_seconds = db.Column(db.Integer, nullable=False, default=2)
|
|
last_triggered = db.Column(db.DateTime, nullable=True)
|
|
|
|
# Optional scheduled time could be added later (left out of DB intentionally unless required).
|
|
|
|
maps = db.relationship("EventDisplayMap", backref="event", cascade="all, delete-orphan")
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<Event {self.name}>"
|
|
|
|
|
|
class EventDisplayMap(db.Model):
|
|
__tablename__ = "event_display_maps"
|
|
__table_args__ = (
|
|
UniqueConstraint("event_id", "display_id", name="uq_event_display"),
|
|
)
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
event_id = db.Column(db.Integer, db.ForeignKey("events.id"), nullable=False)
|
|
display_id = db.Column(db.Integer, db.ForeignKey("displays.id"), nullable=False)
|
|
video_id = db.Column(db.Integer, db.ForeignKey("videos.id"), nullable=False)
|
|
|
|
display = db.relationship("Display")
|
|
video = db.relationship("Video")
|
|
|
|
|
|
class EventLog(db.Model):
|
|
__tablename__ = "event_logs"
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
event_id = db.Column(db.Integer, db.ForeignKey("events.id"), nullable=False)
|
|
triggered_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
|
|
trigger_source = db.Column(db.String(32), nullable=False) # manual|udp
|
|
source_ip = db.Column(db.String(64), nullable=True)
|
|
|
|
event = db.relationship("Event")
|
|
|
|
|
|
class AppSetting(db.Model):
|
|
__tablename__ = "app_settings"
|
|
|
|
# Small key/value store for global settings (SQLite-friendly)
|
|
key = db.Column(db.String(64), primary_key=True)
|
|
value = db.Column(db.String(255), nullable=False)
|