diff --git a/.env.example b/.env.example index 1f411a0..36ce4c1 100644 --- a/.env.example +++ b/.env.example @@ -184,6 +184,9 @@ VITE_RADAR_FALLBACK_LAYER=radar VITE_RADAR_FALLBACK_MAX_ZOOM=6 # Trail history radius shown on the map (km) VITE_OBSERVATION_RANGE_KM=50 +# Hours since a mesh node's last advert before it is shown as STALE / OFFLINE on the map. +# MeshCore nodes advert only every 24–48 h, so keep this above one advert cycle. +VITE_MESH_NODE_STALE_HOURS=72 # Keep false for normal operation. True enables cleaner map snapshots but costs render performance. VITE_PRESERVE_DRAWING_BUFFER=false diff --git a/frontend/src/config.ts b/frontend/src/config.ts index 02d2617..b874ff3 100644 --- a/frontend/src/config.ts +++ b/frontend/src/config.ts @@ -55,3 +55,11 @@ export const RADAR_FALLBACK_LAYER = import.meta.env.VITE_RADAR_FALLBACK_LAYER || // Observation range ring — radius in km centered on DEFAULT_CENTER. // Set VITE_OBSERVATION_RANGE_KM=0 to hide the ring. export const OBSERVATION_RANGE_KM = Number(import.meta.env.VITE_OBSERVATION_RANGE_KM ?? 50) + +// Mesh node staleness window. A mesh node's last_seen is its last advert +// timestamp, and MeshCore nodes typically advert only once every 24–48 h, so a +// short window marks healthy-but-quiet nodes (including active repeaters) as +// stale. Default 72 h flags a node only after it has missed roughly two advert +// cycles. Override with VITE_MESH_NODE_STALE_HOURS. +export const MESH_NODE_STALE_MS = + Number(import.meta.env.VITE_MESH_NODE_STALE_HOURS ?? 72) * 60 * 60 * 1000 diff --git a/frontend/src/layers/buildMeshNodeLayer.ts b/frontend/src/layers/buildMeshNodeLayer.ts index 6ebd971..bd3f042 100644 --- a/frontend/src/layers/buildMeshNodeLayer.ts +++ b/frontend/src/layers/buildMeshNodeLayer.ts @@ -1,6 +1,7 @@ import { IconLayer } from '@deck.gl/layers' import type { Entity } from '../store' import { getAtlasIcons } from './atlasIcons' +import { MESH_NODE_STALE_MS } from '../config' export interface MeshNodePoint { entity_id: string @@ -11,8 +12,6 @@ export interface MeshNodePoint { status: string } -const STALE_MS = 10 * 60 * 1000 - // Atlas hue: --cat-mesh #FF8F00 const MESH_ACTIVE: [number, number, number, number] = [255, 143, 0, 240] const MESH_STALE: [number, number, number, number] = [136, 136, 136, 200] @@ -20,7 +19,7 @@ const MESH_STALE: [number, number, number, number] = [136, 136, 136, 200] function toMeshNodePoint(e: Entity, nowMs: number): MeshNodePoint | null { if (e.entity_type !== 'mesh_node' || e.lat == null || e.lon == null) return null const lastMs = e.last_seen ? Date.parse(e.last_seen) : 0 - const stale = !lastMs || (nowMs - lastMs > STALE_MS) + const stale = !lastMs || (nowMs - lastMs > MESH_NODE_STALE_MS) return { entity_id: e.entity_id, name: e.display_name ?? e.entity_id,