feat: add mqtt pipeline tables and models

This commit is contained in:
魏风
2026-03-17 13:10:50 +08:00
parent 624dcc3bff
commit 27101e9bff
3 changed files with 342 additions and 2 deletions

View File

@@ -1,8 +1,9 @@
import uuid
from datetime import datetime, timezone
from typing import Any
from pydantic import EmailStr
from sqlalchemy import DateTime
from sqlalchemy import JSON, DateTime, LargeBinary
from sqlmodel import Field, Relationship, SQLModel
@@ -53,7 +54,9 @@ class User(UserBase, table=True):
default_factory=get_datetime_utc,
sa_type=DateTime(timezone=True), # type: ignore
)
locations: list["Location"] = Relationship(back_populates="owner", cascade_delete=True)
locations: list["Location"] = Relationship(
back_populates="owner", cascade_delete=True
)
# Properties to return via API, id is always required
@@ -108,6 +111,99 @@ class LocationsPublic(SQLModel):
count: int
class TerminalMessageRaw(SQLModel, table=True):
__tablename__ = "terminal_message_raw"
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
device_id: str = Field(max_length=255, index=True)
topic: str = Field(max_length=255)
received_at: datetime = Field(
default_factory=get_datetime_utc,
sa_type=DateTime(timezone=True), # type: ignore
)
payload_bytes: bytes = Field(sa_type=LargeBinary) # type: ignore
payload_size: int = 0
payload_sha256: str = Field(default="", max_length=64, index=True)
qos: int = 0
retain: bool = False
parse_status: str = Field(default="pending", max_length=32, index=True)
parse_attempts: int = 0
next_retry_at: datetime | None = Field(
default=None,
sa_type=DateTime(timezone=True), # type: ignore
index=True,
)
parse_error: str | None = Field(default=None, max_length=1024)
created_at: datetime = Field(
default_factory=get_datetime_utc,
sa_type=DateTime(timezone=True), # type: ignore
)
class TerminalObservationEvent(SQLModel, table=True):
__tablename__ = "terminal_observation_event"
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
raw_id: uuid.UUID = Field(
foreign_key="terminal_message_raw.id", nullable=False, index=True
)
device_id: str = Field(max_length=255, index=True)
event_time: datetime = Field(
default_factory=get_datetime_utc,
sa_type=DateTime(timezone=True), # type: ignore
index=True,
)
event_type: str = Field(max_length=64, index=True)
payload_json: dict[str, Any] = Field(default_factory=dict, sa_type=JSON) # type: ignore
created_at: datetime = Field(
default_factory=get_datetime_utc,
sa_type=DateTime(timezone=True), # type: ignore
)
class TerminalDeviceState(SQLModel, table=True):
__tablename__ = "terminal_device_state"
device_id: str = Field(max_length=255, primary_key=True)
last_event_time: datetime | None = Field(
default=None, sa_type=DateTime(timezone=True)
) # type: ignore
fix_status: str | None = Field(default=None, max_length=64)
lat: float | None = None
lon: float | None = None
alt_m: float | None = None
satellites_used: int | None = None
satellite_signal_summary: dict[str, Any] | None = Field(default=None, sa_type=JSON) # type: ignore
rtcm_type_summary: dict[str, Any] | None = Field(default=None, sa_type=JSON) # type: ignore
updated_at: datetime = Field(
default_factory=get_datetime_utc,
sa_type=DateTime(timezone=True), # type: ignore
)
class TerminalRawArchiveManifest(SQLModel, table=True):
__tablename__ = "terminal_raw_archive_manifest"
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
device_id: str = Field(max_length=255, index=True)
range_start: datetime = Field(
sa_type=DateTime(timezone=True), # type: ignore
index=True,
)
range_end: datetime = Field(
sa_type=DateTime(timezone=True), # type: ignore
index=True,
)
file_path: str = Field(max_length=1024, unique=True)
file_size: int = 0
sha256: str = Field(max_length=64)
record_count: int = 0
created_at: datetime = Field(
default_factory=get_datetime_utc,
sa_type=DateTime(timezone=True), # type: ignore
)
# Generic message
class Message(SQLModel):
message: str