Skip to main content

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​

StreamDescrizioneProducerConsumer
positions:rawPosizioni grezze dal decoderDecoderPositions Service
positions:validatedPosizioni validate e arricchitePositions ServiceWebSocket, Events
presenceStatus online/offlineDecoderWebSocket
eventsAllarmi, geofence, etc.Events ServiceWebSocket, Notification

πŸ“Š Campi Position​

Campi Core (sempre presenti)​

CampoTipoDescrizione
deviceIdlongID univoco del device
protocolstringNome protocollo (s21l, v6c, g11lse, etc.)
deviceTimetimestampOra del dispositivo
fixTimetimestampOra fix GPS
serverTimetimestampOra ricezione server
latitudedoubleLatitudine
longitudedoubleLongitudine
altitudedoubleAltitudine (metri)
speeddoubleVelocitΓ  (knots)
coursedoubleDirezione (gradi)
validbooleanGPS valido

Campi Arricchiti (aggiunti dal Positions Service)​

CampoTipoDescrizione
distancedoubleDistanza dall'ultima posizione (metri)
totalDistancedoubleDistanza totale cumulativa (metri)
motionbooleanIn movimento (speed > threshold)

Campi Status​

CampoTipoDescrizione
ignitionbooleanContatto acceso
motionbooleanIn movimento
blockedbooleanDispositivo bloccato
chargingbooleanIn carica

Campi Power​

CampoTipoDescrizione
batteryLevelintegerPercentuale batteria (0-100)
batterydoubleTensione batteria (V)
powerdoubleTensione alimentazione esterna (V)

Campi Network/GPS​

CampoTipoDescrizione
rssiintegerPotenza segnale GSM (0-100)
satellitesintegerNumero satelliti GPS
hdopdoublePrecisione orizzontale GPS

Campi Cell Tower​

CampoTipoDescrizione
cellIdlongCell ID
lacintegerLocation Area Code
mccintegerMobile Country Code
mncintegerMobile Network Code

Campi Odometer​

CampoTipoDescrizione
odometerlongContachilometri totale (metri)
odometerTripdoubleContachilometri viaggio (metri)
hourslongOre motore

Campi OBD​

CampoTipoDescrizione
obdSpeedintegerVelocitΓ  da OBD (km/h)
obdOdometerlongChilometraggio da OBD
rpmintegerGiri motore
throttledoublePosizione acceleratore (%)
engineLoaddoubleCarico motore (%)
coolantTempintegerTemperatura liquido raffreddamento (Β°C)

Campi Fuel​

CampoTipoDescrizione
fuelLeveldoubleLivello carburante (%)
fuelConsumptiondoubleConsumo carburante (L/100km)
fuelUseddoubleCarburante usato (L)

Campi Allarmi​

CampoTipoDescrizione
alarmstringTipo allarme corrente
alarmsarray[string]Lista allarmi attivi
eventintegerCodice evento protocollo
statusintegerCodice status protocollo

Campi Driver/IO​

CampoTipoDescrizione
driverstringNome autista
driverIdstringID autista (iButton, RFID)
inputlongInput digitali (bitmask)
outputlongOutput digitali (bitmask)
io1integerInput digitale 1
adc1doubleInput analogico 1
adc2doubleInput analogico 2

Campi Vehicle​

CampoTipoDescrizione
vinstringVehicle Identification Number
dtcsstringDiagnostic Trouble Codes

Campi Altri​

CampoTipoDescrizione
iccidstringID SIM card
gSensorstringDati accelerometro
tiltstringAngolo inclinazione
geofenceintegerID geofence corrente
wakeSourceintegerCausa risveglio

Campi Complessi (JSONB)​

CampoTipoDescrizione
networkobjectInfo rete completa
cellTowersarrayLista cell tower
wifiAccessPointsarrayLista WiFi AP
temperaturesarraySensori temperatura
locksobjectStato serrature
geofenceIdsarrayID geofence attivi
attributesobjectCampi 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​

CampoTipoDescrizione
statusstring"online" / "offline"
last_updatetimestampUltimo aggiornamento
position_idbigintFK 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:

  1. Al login/avvio: GET /api/devices + GET /api/positions
  2. Connessione WebSocket per aggiornamenti real-time
  3. Push notifications per allarmi critici (via Firebase/APNs)

Differenze Mobile:​

AspettoWeb AppMobile App
WebSocketSempre connessoBackground limitato
NotificheToast in-appPush notifications
OfflineNon supportatoCache locale
BackgroundTab switch = pauseApp lifecycle management

Background Behavior (Mobile)​

Quando l'app va in background:

  1. WebSocket viene chiuso
  2. Push notifications attive per allarmi critici
  3. Al ritorno in foreground:
    • Re-fetch GET /api/devices + GET /api/positions
    • Re-connect WebSocket

πŸ” Autenticazione​

ClientMetodo
Web AppCookie httpOnly (access_token)
Mobile AppsBearer Token (header Authorization)
WebSocketToken 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​

  1. Single Source of Truth: Database Γ¨ la fonte, non cache
  2. Persistenza: Stato sopravvive ai riavvii
  3. Consistenza: API e WebSocket danno gli stessi dati
  4. Performance: Colonne dedicate per query veloci
  5. ScalabilitΓ : WebSocket stateless, puΓ² scalare orizzontalmente