• Creato un nuovo file CSS per gli stili del chiosco (kiosk) con variabili, stili per le schede (card) e animazioni. • Aggiunto un file HTML per l'interfaccia della mappa utilizzando Mapbox, inclusi gli stili e il JavaScript per le funzionalità della mappa. • Introdotto un file JSON per i riferimenti ai sensori, definendo percorsi ed elementi per i dati di temperatura, vento, onde, posizione, batteria, motore e sistema. Co-authored-by: Copilot <copilot@github.com>
115 lines
3.2 KiB
JavaScript
115 lines
3.2 KiB
JavaScript
const WebSocket = require('ws');
|
|
const os = require('os');
|
|
const { encode } = require('@msgpack/msgpack');
|
|
|
|
const SOCKET_URL = process.env.REALTIME_SOCKET_URL;
|
|
|
|
let ws = null;
|
|
let onDisconnect = null;
|
|
|
|
/**
|
|
* Apre una connessione WebSocket al server realtime usando il token temporaneo.
|
|
* @param {string} socketToken - Token temporaneo ottenuto da auth.authenticate()
|
|
* @param {Function} onClose - Callback chiamata quando la connessione si chiude
|
|
* @returns {Promise<boolean>} true se la connessione è riuscita
|
|
*/
|
|
function connect(socketToken, onClose) {
|
|
return new Promise((resolve) => {
|
|
if (!SOCKET_URL) {
|
|
console.error('[REALTIME|WS] REALTIME_SOCKET_URL non configurato nel .env');
|
|
return resolve(false);
|
|
}
|
|
|
|
onDisconnect = onClose;
|
|
|
|
try {
|
|
const wsUrl = `${SOCKET_URL}/?token=${encodeURIComponent(socketToken)}`;
|
|
ws = new WebSocket(wsUrl);
|
|
} catch (err) {
|
|
console.error('[REALTIME|WS] Errore creazione:', err.message);
|
|
return resolve(false);
|
|
}
|
|
|
|
ws.on('open', () => {
|
|
console.log('[REALTIME|WS] Connesso');
|
|
// Invia init con system uptime
|
|
const initPayload = {
|
|
_t: 'init',
|
|
uptime: Math.floor(os.uptime())
|
|
};
|
|
ws.send(encode(initPayload));
|
|
console.log('[REALTIME|WS] Init inviato:', initPayload);
|
|
resolve(true);
|
|
});
|
|
|
|
ws.on('message', () => {
|
|
// Il server non invia messaggi ai sensori per ora
|
|
});
|
|
|
|
ws.on('ping', () => {
|
|
// ws risponde automaticamente con pong
|
|
});
|
|
|
|
ws.on('error', (err) => {
|
|
console.error(`[REALTIME|WS] Errore: ${err.message}`);
|
|
resolve(false);
|
|
});
|
|
|
|
ws.on('close', (code) => {
|
|
console.log(`[REALTIME|WS] Disconnesso (code: ${code})`);
|
|
ws = null;
|
|
if (onDisconnect) onDisconnect();
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Invia dati al server tramite WebSocket, codificati in msgpack.
|
|
* @param {Array} data - Array nel formato [timestamp, measurement, fields]
|
|
*/
|
|
function send(data) {
|
|
if (!ws || ws.readyState !== WebSocket.OPEN) return;
|
|
|
|
try {
|
|
const [timestamp, measurement, fields] = data;
|
|
const packet = { ts: timestamp, _m: measurement, ...fields };
|
|
ws.send(encode(packet));
|
|
} catch (err) {
|
|
console.error('[REALTIME|WS] Errore invio:', err.message);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Invia un oggetto raw al server, codificato in msgpack.
|
|
* A differenza di send(), non fa transform [ts, measurement, fields].
|
|
* @param {Object} obj - Oggetto da inviare direttamente
|
|
*/
|
|
function sendRaw(obj) {
|
|
if (!ws || ws.readyState !== WebSocket.OPEN) return;
|
|
try {
|
|
ws.send(encode(obj));
|
|
} catch (err) {
|
|
console.error('[REALTIME|WS] Errore invio raw:', err.message);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @returns {boolean} true se la connessione è attiva
|
|
*/
|
|
function isConnected() {
|
|
return ws !== null && ws.readyState === WebSocket.OPEN;
|
|
}
|
|
|
|
/**
|
|
* Chiude la connessione WebSocket.
|
|
*/
|
|
function close() {
|
|
onDisconnect = null;
|
|
if (ws) {
|
|
ws.close();
|
|
ws = null;
|
|
}
|
|
}
|
|
|
|
module.exports = { connect, send, sendRaw, isConnected, close };
|