111 lines
4.9 KiB
Python
111 lines
4.9 KiB
Python
from sqlalchemy import Column, String, DateTime, Boolean, Text, Date, Integer
|
|
from datetime import datetime
|
|
from app.seismo.database import Base
|
|
|
|
|
|
class Emitter(Base):
|
|
__tablename__ = "emitters"
|
|
|
|
id = Column(String, primary_key=True, index=True)
|
|
unit_type = Column(String, nullable=False)
|
|
last_seen = Column(DateTime, default=datetime.utcnow)
|
|
last_file = Column(String, nullable=False)
|
|
status = Column(String, nullable=False)
|
|
notes = Column(String, nullable=True)
|
|
|
|
|
|
class RosterUnit(Base):
|
|
"""
|
|
Roster table: represents our *intended assignment* of a unit.
|
|
This is editable from the GUI.
|
|
|
|
Supports multiple device types (seismograph, modem, sound_level_meter) with type-specific fields.
|
|
"""
|
|
__tablename__ = "roster"
|
|
|
|
# Core fields (all device types)
|
|
id = Column(String, primary_key=True, index=True)
|
|
unit_type = Column(String, default="series3") # Backward compatibility
|
|
device_type = Column(String, default="seismograph") # "seismograph" | "modem" | "sound_level_meter"
|
|
deployed = Column(Boolean, default=True)
|
|
retired = Column(Boolean, default=False)
|
|
note = Column(String, nullable=True)
|
|
project_id = Column(String, nullable=True)
|
|
location = Column(String, nullable=True) # Legacy field - use address/coordinates instead
|
|
address = Column(String, nullable=True) # Human-readable address
|
|
coordinates = Column(String, nullable=True) # Lat,Lon format: "34.0522,-118.2437"
|
|
last_updated = Column(DateTime, default=datetime.utcnow)
|
|
|
|
# Seismograph-specific fields (nullable for modems and SLMs)
|
|
last_calibrated = Column(Date, nullable=True)
|
|
next_calibration_due = Column(Date, nullable=True)
|
|
|
|
# Modem assignment (shared by seismographs and SLMs)
|
|
deployed_with_modem_id = Column(String, nullable=True) # FK to another RosterUnit (device_type=modem)
|
|
|
|
# Modem-specific fields (nullable for seismographs and SLMs)
|
|
ip_address = Column(String, nullable=True)
|
|
phone_number = Column(String, nullable=True)
|
|
hardware_model = Column(String, nullable=True)
|
|
|
|
# Sound Level Meter-specific fields (nullable for seismographs and modems)
|
|
slm_host = Column(String, nullable=True) # Device IP or hostname
|
|
slm_tcp_port = Column(Integer, nullable=True) # TCP control port (default 2255)
|
|
slm_ftp_port = Column(Integer, nullable=True) # FTP data retrieval port (default 21)
|
|
slm_model = Column(String, nullable=True) # NL-43, NL-53, etc.
|
|
slm_serial_number = Column(String, nullable=True) # Device serial number
|
|
slm_frequency_weighting = Column(String, nullable=True) # A, C, Z
|
|
slm_time_weighting = Column(String, nullable=True) # F (Fast), S (Slow), I (Impulse)
|
|
slm_measurement_range = Column(String, nullable=True) # e.g., "30-130 dB"
|
|
slm_last_check = Column(DateTime, nullable=True) # Last communication check
|
|
|
|
|
|
class IgnoredUnit(Base):
|
|
"""
|
|
Ignored units: units that report but should be filtered out from unknown emitters.
|
|
Used to suppress noise from old projects.
|
|
"""
|
|
__tablename__ = "ignored_units"
|
|
|
|
id = Column(String, primary_key=True, index=True)
|
|
reason = Column(String, nullable=True)
|
|
ignored_at = Column(DateTime, default=datetime.utcnow)
|
|
|
|
|
|
class UnitHistory(Base):
|
|
"""
|
|
Unit history: complete timeline of changes to each unit.
|
|
Tracks note changes, status changes, deployment/benched events, and more.
|
|
"""
|
|
__tablename__ = "unit_history"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
unit_id = Column(String, nullable=False, index=True) # FK to RosterUnit.id
|
|
change_type = Column(String, nullable=False) # note_change, deployed_change, retired_change, etc.
|
|
field_name = Column(String, nullable=True) # Which field changed
|
|
old_value = Column(Text, nullable=True) # Previous value
|
|
new_value = Column(Text, nullable=True) # New value
|
|
changed_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
|
source = Column(String, default="manual") # manual, csv_import, telemetry, offline_sync
|
|
notes = Column(Text, nullable=True) # Optional reason/context for the change
|
|
|
|
|
|
class UserPreferences(Base):
|
|
"""
|
|
User preferences: persistent storage for application settings.
|
|
Single-row table (id=1) to store global user preferences.
|
|
"""
|
|
__tablename__ = "user_preferences"
|
|
|
|
id = Column(Integer, primary_key=True, default=1)
|
|
timezone = Column(String, default="America/New_York")
|
|
theme = Column(String, default="auto") # auto, light, dark
|
|
auto_refresh_interval = Column(Integer, default=10) # seconds
|
|
date_format = Column(String, default="MM/DD/YYYY")
|
|
table_rows_per_page = Column(Integer, default=25)
|
|
calibration_interval_days = Column(Integer, default=365)
|
|
calibration_warning_days = Column(Integer, default=30)
|
|
status_ok_threshold_hours = Column(Integer, default=12)
|
|
status_pending_threshold_hours = Column(Integer, default=24)
|
|
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|