74 lines
3.2 KiB
Python
74 lines
3.2 KiB
Python
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, String, Text
|
|
from sqlalchemy.dialects.postgresql import ARRAY, JSONB
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from .base import Base, TimestampMixin
|
|
|
|
DEVICE_CATEGORIES = ("raspberry", "mikrotik", "camera", "embedded", "server", "other")
|
|
DEVICE_ROLES = ("entry", "exit", "server", "nvr", "switch", "other")
|
|
DEVICE_STATUSES = ("online", "offline", "unknown")
|
|
DEVICE_SOURCES = ("auto_sync", "manual", "csv_import", "sheets_sync")
|
|
|
|
|
|
class Device(Base, TimestampMixin):
|
|
__tablename__ = "devices"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
|
object_id: Mapped[int] = mapped_column(
|
|
Integer,
|
|
ForeignKey("objects.id", ondelete="RESTRICT"),
|
|
nullable=False,
|
|
index=True,
|
|
)
|
|
|
|
ip: Mapped[str] = mapped_column(String(45), nullable=False)
|
|
hostname: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
|
|
mac: Mapped[Optional[str]] = mapped_column(String(17), nullable=True)
|
|
|
|
# Classification
|
|
category: Mapped[str] = mapped_column(String(20), nullable=False, default="other")
|
|
role: Mapped[str] = mapped_column(String(20), nullable=False, default="other")
|
|
model: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
|
|
firmware_version: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
|
|
|
|
# Source tracking
|
|
source: Mapped[str] = mapped_column(String(20), nullable=False, default="manual")
|
|
external_id: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
|
|
|
|
# SSH overrides (NULL = use object defaults)
|
|
ssh_user_override: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
|
|
ssh_pass_override_enc: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
|
|
ssh_port_override: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
|
|
|
|
# Device-specific metadata (Mikrotik API port, RTSP URL, etc.)
|
|
device_meta: Mapped[dict] = mapped_column(JSONB, nullable=False, default=dict)
|
|
|
|
# Capabilities populated by drivers
|
|
capabilities: Mapped[list[str]] = mapped_column(
|
|
ARRAY(String), nullable=False, default=list
|
|
)
|
|
|
|
# Monitoring
|
|
monitor_enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
|
last_seen: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
last_ping_ms: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
|
|
status: Mapped[str] = mapped_column(String(20), nullable=False, default="unknown")
|
|
|
|
rack_id: Mapped[Optional[int]] = mapped_column(
|
|
Integer,
|
|
ForeignKey("racks.id", ondelete="SET NULL"),
|
|
nullable=True,
|
|
index=True,
|
|
)
|
|
|
|
notes: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
|
|
is_active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
|
|
|
|
object: Mapped["Object"] = relationship("Object", back_populates="devices")
|
|
rack: Mapped[Optional["Rack"]] = relationship("Rack", back_populates="devices")
|
|
config_snapshots: Mapped[list["ConfigSnapshot"]] = relationship(
|
|
"ConfigSnapshot", back_populates="device", cascade="all, delete-orphan"
|
|
)
|