Skip to main content

Device Presence System

Il sistema di presenza traccia lo stato online/offline dei dispositivi GPS in tempo reale.

Architettura

Flusso Eventi

Device si connette

  1. Decoder rileva nuova connessione TCP
  2. Pubblica su stream presence:
    {"unique_id": "019175767229", "event": "online", "time": 1702...}
  3. db-persister consuma e aggiorna DB:
    UPDATE devices SET status = 'online', last_update = NOW() WHERE unique_id = '...';
  4. websocket consuma e fa broadcast ai client:
    {"type": "device_status", "data": {"deviceId": 1, "status": "online"}}

Device si disconnette

Due scenari:

TipoDescrizioneTempo rilevamento
Disconnessione pulitaDevice invia FIN packet TCPImmediato
Disconnessione sporcaDevice si spegne improvvisamenteTimeout TCP (30-120s)

Disconnessione TCP

Disconnessione "pulita" (FIN packet)

Device GPS --> FIN --> Server
Server --> ACK --> Device GPS
Server --> FIN --> Device GPS
Device GPS --> ACK --> Server

Risultato: Disconnessione immediata, il decoder rileva subito e pubblica offline

Disconnessione "sporca" (device si spegne)

Device GPS ❌ (nessun pacchetto)
Server --> aspetta... aspetta... --> TIMEOUT!

Risultato: Il server non sa che il device è morto finché non scade il timeout TCP

Soluzioni per Timeout

MetodoCome funziona
TCP Keep-AliveIl server invia periodicamente pacchetti "sei vivo?"
Application-level heartbeatIl device deve inviare un pacchetto ogni X secondi
Timeout applicativoSe non ricevi dati per X minuti → considera offline

Stream Redis

presence

Stream per eventi online/offline dei device.

# Visualizza ultimi 5 eventi
docker exec redis redis-cli XRANGE presence - + COUNT 5

# Leggi in tempo reale
docker exec redis redis-cli XREAD BLOCK 0 STREAMS presence $

# Conta eventi
docker exec redis redis-cli XLEN presence

Formato messaggio:

unique_id: "019175767229"
device_id: "1" # ID interno decoder (non database!)
event: "online" | "offline"
time: "1702..."
remote: "192.168.1.1:12345"

Consumer

db-persister

Consuma stream presence con consumer group persister-workers:

  • Aggiorna devices.status nel database
  • Aggiorna devices.last_update
  • Log: Device XXXXX status updated to 'online'

websocket

Consuma stream presence con xread semplice:

  • Cerca device_id reale nel DB tramite unique_id
  • Broadcasting device_status a tutti gli utenti autorizzati
  • Log: Broadcasted device X status 'online' to Y users

Web App

La web-app ottiene lo status in due modi:

  1. All'avvio - REST API GET /api/devices:

    {"id": 1, "name": "PET", "status": "online", ...}
  2. In tempo reale - WebSocket:

    {"type": "device_status", "data": {"deviceId": 1, "status": "online"}}

Grafana Dashboard

Dashboard Device Presence Monitor mostra:

  • 🟢 Devices Online Now
  • 🔴 Devices Offline (5m)
  • 📈 Online/Offline Events Over Time
  • 📊 Status Distribution
  • 📜 Presence Events Log