76 lines
2.6 KiB
Python
76 lines
2.6 KiB
Python
"""Vessel AIS models for live maritime tracking."""
|
|
|
|
from sqlalchemy import BigInteger, Column, DateTime, Float, Index, Integer, SmallInteger, String
|
|
from sqlalchemy.sql import func
|
|
|
|
from app.core.time import to_iso8601_utc
|
|
from app.db.session import Base
|
|
|
|
|
|
class VesselStatic(Base):
|
|
"""Slow-changing vessel identity and dimensions."""
|
|
|
|
__tablename__ = "vessel_static"
|
|
|
|
mmsi = Column(BigInteger, primary_key=True)
|
|
name = Column(String(128), nullable=True)
|
|
callsign = Column(String(16), nullable=True)
|
|
vessel_type = Column(SmallInteger, nullable=True, index=True)
|
|
vessel_type_name = Column(String(64), nullable=True, index=True)
|
|
flag = Column(String(4), nullable=True, index=True)
|
|
length = Column(Float, nullable=True)
|
|
width = Column(Float, nullable=True)
|
|
draught = Column(Float, nullable=True)
|
|
imo = Column(BigInteger, nullable=True)
|
|
updated_at = Column(DateTime(timezone=True), nullable=False, server_default=func.now())
|
|
|
|
def to_dict(self) -> dict:
|
|
return {
|
|
"mmsi": self.mmsi,
|
|
"name": self.name,
|
|
"callsign": self.callsign,
|
|
"vessel_type": self.vessel_type,
|
|
"vessel_type_name": self.vessel_type_name,
|
|
"flag": self.flag,
|
|
"length": self.length,
|
|
"width": self.width,
|
|
"draught": self.draught,
|
|
"imo": self.imo,
|
|
"updated_at": to_iso8601_utc(self.updated_at),
|
|
}
|
|
|
|
|
|
class VesselPosition(Base):
|
|
"""Append-only AIS positions retained for short history windows."""
|
|
|
|
__tablename__ = "vessel_position"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
mmsi = Column(BigInteger, nullable=False, index=True)
|
|
lat = Column(Float, nullable=False)
|
|
lon = Column(Float, nullable=False)
|
|
sog = Column(Float, nullable=True)
|
|
cog = Column(Float, nullable=True)
|
|
heading = Column(SmallInteger, nullable=True)
|
|
nav_status = Column(SmallInteger, nullable=True, index=True)
|
|
received_at = Column(DateTime(timezone=True), nullable=False, server_default=func.now(), index=True)
|
|
|
|
__table_args__ = (
|
|
Index("idx_vessel_pos_mmsi_time", "mmsi", "received_at"),
|
|
Index("idx_vessel_pos_time", "received_at"),
|
|
Index("idx_vessel_pos_lat_lon", "lat", "lon"),
|
|
)
|
|
|
|
def to_dict(self) -> dict:
|
|
return {
|
|
"id": self.id,
|
|
"mmsi": self.mmsi,
|
|
"lat": self.lat,
|
|
"lon": self.lon,
|
|
"sog": self.sog,
|
|
"cog": self.cog,
|
|
"heading": self.heading,
|
|
"nav_status": self.nav_status,
|
|
"received_at": to_iso8601_utc(self.received_at),
|
|
}
|