Data Flow Architecture
Questo documento descrive il flusso dei dati dalla ricezione sul decoder alla visualizzazione nelle app (Web, iOS, Android).
π Overview del Flussoβ
βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ
β DEVICE β βββΆ β DECODER β βββΆ β REDIS β βββΆ β SERVICES β
β (GPS/IoT) β TCP β (Java) β β Streams β β (Python) β
βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ
β
βββββββββββββββ βββββββββββββββ β
β FRONTEND β βββ β WEBSOCKET β βββββββββββ
β (Web/Mobile)β β (Python) β
βββββββββββββββ βββββββββββββββ
π¦ Redis Streamsβ
| Stream | Descrizione | Producer | Consumer |
|---|---|---|---|
positions:raw | Posizioni grezze dal decoder | Decoder | Positions Service |
positions:validated | Posizioni validate e arricchite | Positions Service | WebSocket, Events |
presence | Status online/offline | Decoder | WebSocket |
events | Allarmi, geofence, etc. | Events Service | WebSocket, Notification |
π Campi Positionβ
Campi Core (sempre presenti)β
| Campo | Tipo | Descrizione |
|---|---|---|
deviceId | long | ID univoco del device |
protocol | string | Nome protocollo (s21l, v6c, g11lse, etc.) |
deviceTime | timestamp | Ora del dispositivo |
fixTime | timestamp | Ora fix GPS |
serverTime | timestamp | Ora ricezione server |
latitude | double | Latitudine |
longitude | double | Longitudine |
altitude | double | Altitudine (metri) |
speed | double | VelocitΓ (knots) |
course | double | Direzione (gradi) |
valid | boolean | GPS valido |
Campi Arricchiti (aggiunti dal Positions Service)β
| Campo | Tipo | Descrizione |
|---|---|---|
distance | double | Distanza dall'ultima posizione (metri) |
totalDistance | double | Distanza totale cumulativa (metri) |
motion | boolean | In movimento (speed > threshold) |
Campi Statusβ
| Campo | Tipo | Descrizione |
|---|---|---|
ignition | boolean | Contatto acceso |
motion | boolean | In movimento |
blocked | boolean | Dispositivo bloccato |
charging | boolean | In carica |
Campi Powerβ
| Campo | Tipo | Descrizione |
|---|---|---|
batteryLevel | integer | Percentuale batteria (0-100) |
battery | double | Tensione batteria (V) |
power | double | Tensione alimentazione esterna (V) |
Campi Network/GPSβ
| Campo | Tipo | Descrizione |
|---|---|---|
rssi | integer | Potenza segnale GSM (0-100) |
satellites | integer | Numero satelliti GPS |
hdop | double | Precisione orizzontale GPS |
Campi Cell Towerβ
| Campo | Tipo | Descrizione |
|---|---|---|
cellId | long | Cell ID |
lac | integer | Location Area Code |
mcc | integer | Mobile Country Code |
mnc | integer | Mobile Network Code |
Campi Odometerβ
| Campo | Tipo | Descrizione |
|---|---|---|
odometer | long | Contachilometri totale (metri) |
odometerTrip | double | Contachilometri viaggio (metri) |
hours | long | Ore motore |
Campi OBDβ
| Campo | Tipo | Descrizione |
|---|---|---|
obdSpeed | integer | VelocitΓ da OBD (km/h) |
obdOdometer | long | Chilometraggio da OBD |
rpm | integer | Giri motore |
throttle | double | Posizione acceleratore (%) |
engineLoad | double | Carico motore (%) |
coolantTemp | integer | Temperatura liquido raffreddamento (Β°C) |
Campi Fuelβ
| Campo | Tipo | Descrizione |
|---|---|---|
fuelLevel | double | Livello carburante (%) |
fuelConsumption | double | Consumo carburante (L/100km) |
fuelUsed | double | Carburante usato (L) |
Campi Allarmiβ
| Campo | Tipo | Descrizione |
|---|---|---|
alarm | string | Tipo allarme corrente |
alarms | array[string] | Lista allarmi attivi |
event | integer | Codice evento protocollo |
status | integer | Codice status protocollo |
Campi Driver/IOβ
| Campo | Tipo | Descrizione |
|---|---|---|
driver | string | Nome autista |
driverId | string | ID autista (iButton, RFID) |
input | long | Input digitali (bitmask) |
output | long | Output digitali (bitmask) |
io1 | integer | Input digitale 1 |
adc1 | double | Input analogico 1 |
adc2 | double | Input analogico 2 |
Campi Vehicleβ
| Campo | Tipo | Descrizione |
|---|---|---|
vin | string | Vehicle Identification Number |
dtcs | string | Diagnostic Trouble Codes |
Campi Altriβ
| Campo | Tipo | Descrizione |
|---|---|---|
iccid | string | ID SIM card |
gSensor | string | Dati accelerometro |
tilt | string | Angolo inclinazione |
geofence | integer | ID geofence corrente |
wakeSource | integer | Causa risveglio |
Campi Complessi (JSONB)β
| Campo | Tipo | Descrizione |
|---|---|---|
network | object | Info rete completa |
cellTowers | array | Lista cell tower |
wifiAccessPoints | array | Lista WiFi AP |
temperatures | array | Sensori temperatura |
locks | object | Stato serrature |
geofenceIds | array | ID geofence attivi |
attributes | object | Campi custom/sconosciuti |
ποΈ Database Schemaβ
Tabella positions (PostgreSQL)β
Tutti i campi position sono ora colonne dedicate per query performanti.
Solo i campi sconosciuti/custom vanno nella colonna attributes JSONB.
Tabella user_device_attributesβ
| Campo | Tipo | Descrizione |
|---|---|---|
status | string | "online" / "offline" |
last_update | timestamp | Ultimo aggiornamento |
position_id | bigint | FK a positions.id (ultima posizione) |
π± Pattern "Load + Subscribe" (Web & Mobile)β
Tutte le app client (Web, iOS, Android) seguono lo stesso pattern:
1. Al Caricamento (Load)β
// Chiamate API iniziali
const devices = await api.get('/api/devices');
// Restituisce per ogni device:
// - id, name, status (online/offline), lastUpdate, positionId, ...
const positions = await api.get('/api/positions');
// Restituisce ultima posizione per ogni device:
// - latitude, longitude, speed, battery, rssi, ...
// Mostra i dati sulla mappa
renderDevices(devices, positions);
2. In Real-Time (Subscribe)β
// Connessione WebSocket
const ws = new WebSocket('wss://api.vislagps.com/ws');
// Ascolto aggiornamenti
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
switch (msg.type) {
case 'position':
// Nuova posizione β aggiorna mappa
updateDevicePosition(msg.data);
break;
case 'device_status':
// Online/offline β aggiorna icona
updateDeviceStatus(msg.data.deviceId, msg.data.status);
break;
case 'event':
// Allarme β mostra notifica
showEventNotification(msg.data);
break;
}
};
Flusso Completoβ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β APP STARTUP β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β 1. GET /api/devices 2. GET /api/positions β
β β β β
β ββββββββββββββββ ββββββββββββββββ β
β β status β β latitude β β
β β lastUpdate β β longitude β β
β β positionId β β speed β β
β β name, icon β β battery β β
β ββββββββββββββββ β rssi, etc. β β
β ββββββββββββββββ β
β β
β 3. RENDER β Mostra mappa con posizioni e status β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β REAL-TIME β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β 4. WebSocket Connect β Subscribe a updates β
β β
β 5. On message: β
β - position β Muovi marker β
β - device_status β Cambia icona online/offline β
β - event β Toast notifica β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π² Mobile Apps (iOS & Android)β
SΓ, le app mobile usano la stessa logica:
- Al login/avvio:
GET /api/devices+GET /api/positions - Connessione WebSocket per aggiornamenti real-time
- Push notifications per allarmi critici (via Firebase/APNs)
Differenze Mobile:β
| Aspetto | Web App | Mobile App |
|---|---|---|
| WebSocket | Sempre connesso | Background limitato |
| Notifiche | Toast in-app | Push notifications |
| Offline | Non supportato | Cache locale |
| Background | Tab switch = pause | App lifecycle management |
Background Behavior (Mobile)β
Quando l'app va in background:
- WebSocket viene chiuso
- Push notifications attive per allarmi critici
- Al ritorno in foreground:
- Re-fetch
GET /api/devices+GET /api/positions - Re-connect WebSocket
- Re-fetch
π Autenticazioneβ
| Client | Metodo |
|---|---|
| Web App | Cookie httpOnly (access_token) |
| Mobile Apps | Bearer Token (header Authorization) |
| WebSocket | Token nel query param (?token=...) |
π‘ WebSocket Messagesβ
Position Updateβ
{
"type": "position",
"data": {
"deviceId": 123,
"latitude": 45.4642,
"longitude": 9.1900,
"speed": 45.5,
"altitude": 150,
"course": 180,
"valid": true,
"motion": true,
"ignition": true,
"battery": 85.5,
"rssi": 90,
"distance": 125.5,
"totalDistance": 50234.7,
"serverTime": "2024-12-30T22:00:00Z"
}
}
Device Status Updateβ
{
"type": "device_status",
"data": {
"deviceId": 123,
"protocolId": "999999999321",
"status": "online"
}
}
Event Notificationβ
{
"type": "event",
"data": {
"id": 456,
"type": "alarm",
"deviceId": 123,
"attributes": {
"alarm": "sos"
},
"eventTime": "2024-12-30T22:00:00Z"
}
}
β Vantaggi Architetturaβ
- Single Source of Truth: Database Γ¨ la fonte, non cache
- Persistenza: Stato sopravvive ai riavvii
- Consistenza: API e WebSocket danno gli stessi dati
- Performance: Colonne dedicate per query veloci
- ScalabilitΓ : WebSocket stateless, puΓ² scalare orizzontalmente