feat(devices): add DeviceHealthSettings model for per-device alert thresholds
Two-tier (warning/critical) threshold config per device — restarts/week, RSSI floor, free-heap floor, CPU temp ceiling, plus an offline timeout used for both a client-computed health status icon and the Health tab chart's gap detection. Purely advisory for now: no server-side email/push alerting infra exists yet, so email_on_threshold and push_on_crash_boot are placeholders for that future work. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -98,6 +98,35 @@ class DeviceStatistics(BaseModel):
|
||||
maintainancePeriod: int = 0
|
||||
|
||||
|
||||
class HealthThresholdTier(BaseModel):
|
||||
"""One severity tier's worth of metric thresholds. Two tiers (warning,
|
||||
critical) make up DeviceHealthSettings — see there for why."""
|
||||
restarts_per_week_threshold: int
|
||||
rssi_floor_dbm: int
|
||||
free_heap_floor_kb: int
|
||||
cpu_temp_ceiling_c: int
|
||||
|
||||
|
||||
class DeviceHealthSettings(BaseModel):
|
||||
"""Per-device alert thresholds shown/edited on the Health tab's Settings
|
||||
sub-tab. Purely advisory today — thresholds drive a client-computed
|
||||
ok/warning/critical status icon, not any server-side alerting yet (no
|
||||
email/push infra exists). Two severity tiers per metric (warning fires
|
||||
first, critical is the harder breach) so the header status icon can show
|
||||
orange vs. red rather than a single degraded/healthy binary.
|
||||
offline_timeout_sec also feeds the Health tab's chart gap detection
|
||||
(LineChart's gapThresholdMs) so both share one source of truth."""
|
||||
warning: HealthThresholdTier = HealthThresholdTier(
|
||||
restarts_per_week_threshold=6, rssi_floor_dbm=-80, free_heap_floor_kb=30, cpu_temp_ceiling_c=65,
|
||||
)
|
||||
critical: HealthThresholdTier = HealthThresholdTier(
|
||||
restarts_per_week_threshold=12, rssi_floor_dbm=-90, free_heap_floor_kb=15, cpu_temp_ceiling_c=80,
|
||||
)
|
||||
offline_timeout_sec: int = 90
|
||||
email_on_threshold: bool = False
|
||||
push_on_crash_boot: bool = False
|
||||
|
||||
|
||||
class MelodyMainItem(BaseModel):
|
||||
"""Mirrors the Melody schema used in the melodies collection."""
|
||||
information: dict = {}
|
||||
@@ -118,6 +147,7 @@ class DeviceCreate(BaseModel):
|
||||
device_attributes: DeviceAttributes = DeviceAttributes()
|
||||
device_subscription: DeviceSubInformation = DeviceSubInformation()
|
||||
device_stats: DeviceStatistics = DeviceStatistics()
|
||||
device_health_settings: DeviceHealthSettings = DeviceHealthSettings()
|
||||
events_on: bool = False
|
||||
device_location_coordinates: Any = None # GeoPoint dict {lat, lng} or legacy str
|
||||
device_melodies_all: List[MelodyMainItem] = []
|
||||
@@ -143,6 +173,7 @@ class DeviceUpdate(BaseModel):
|
||||
device_attributes: Optional[Dict[str, Any]] = None
|
||||
device_subscription: Optional[Dict[str, Any]] = None
|
||||
device_stats: Optional[Dict[str, Any]] = None
|
||||
device_health_settings: Optional[Dict[str, Any]] = None
|
||||
events_on: Optional[bool] = None
|
||||
device_location_coordinates: Optional[Any] = None # dict {lat, lng} or legacy str
|
||||
device_melodies_all: Optional[List[MelodyMainItem]] = None
|
||||
|
||||
Reference in New Issue
Block a user