Flask API backend for ESP32 sensor fleet: - App factory pattern with blueprints - SQLAlchemy 2.x models (Sensor, Device, Sighting, Alert, Event, Probe) - UDP collector for sensor data streams - REST API endpoints for sensors, devices, alerts, events, probes, stats - pytest setup with fixtures - Containerfile for podman deployment - Makefile for common tasks
38 lines
1.5 KiB
Python
38 lines
1.5 KiB
Python
"""Device model."""
|
|
from datetime import datetime, UTC
|
|
from ..extensions import db
|
|
|
|
|
|
class Device(db.Model):
|
|
"""Discovered BLE/WiFi device."""
|
|
__tablename__ = 'devices'
|
|
|
|
id: db.Mapped[int] = db.mapped_column(primary_key=True)
|
|
mac: db.Mapped[str] = db.mapped_column(db.String(17), unique=True, index=True)
|
|
device_type: db.Mapped[str] = db.mapped_column(db.String(8)) # 'ble' or 'wifi'
|
|
vendor: db.Mapped[str | None] = db.mapped_column(db.String(64), nullable=True)
|
|
name: db.Mapped[str | None] = db.mapped_column(db.String(64), nullable=True)
|
|
first_seen: db.Mapped[datetime] = db.mapped_column(default=lambda: datetime.now(UTC))
|
|
last_seen: db.Mapped[datetime] = db.mapped_column(default=lambda: datetime.now(UTC))
|
|
|
|
# BLE-specific fields
|
|
company_id: db.Mapped[int | None] = db.mapped_column(nullable=True)
|
|
tx_power: db.Mapped[int | None] = db.mapped_column(nullable=True)
|
|
|
|
# Relationships
|
|
sightings = db.relationship('Sighting', back_populates='device', lazy='dynamic')
|
|
probes = db.relationship('Probe', back_populates='device', lazy='dynamic')
|
|
|
|
def to_dict(self):
|
|
return {
|
|
'id': self.id,
|
|
'mac': self.mac,
|
|
'type': self.device_type,
|
|
'vendor': self.vendor,
|
|
'name': self.name,
|
|
'first_seen': self.first_seen.isoformat(),
|
|
'last_seen': self.last_seen.isoformat(),
|
|
'company_id': self.company_id,
|
|
'tx_power': self.tx_power,
|
|
}
|