utp_service/backend/app/models/device.py
2026-04-07 00:00:50 +03:00

63 lines
2.8 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")
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")