@sailingrotevista/rotevista-dash 6.0.6 → 6.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app.js +49 -33
- package/index.js +12 -7
- package/package.json +1 -1
package/app.js
CHANGED
|
@@ -885,10 +885,14 @@ function manageHistory(type, value) {
|
|
|
885
885
|
const samples = Math.max(2, CONFIG.graphs.samples || 60);
|
|
886
886
|
const bucketIntervalMs = (historyMinutes * 60000) / samples;
|
|
887
887
|
|
|
888
|
-
// --- 2. INIT SICURO (
|
|
888
|
+
// --- 2. INIT SICURO (Sintonizzato all'epoca assoluta UTC) ---
|
|
889
889
|
if (!store.graphTempBuf[type]) store.graphTempBuf[type] = [];
|
|
890
890
|
if (!store.histories[type]) store.histories[type] = [];
|
|
891
|
-
|
|
891
|
+
|
|
892
|
+
// SINTONIZZAZIONE DI FASE: Agganciamo il timer iniziale al multiplo UTC più vicino
|
|
893
|
+
if (store.lastUpdates[type] === undefined || store.lastUpdates[type] === 0) {
|
|
894
|
+
store.lastUpdates[type] = Math.floor(now / bucketIntervalMs) * bucketIntervalMs;
|
|
895
|
+
}
|
|
892
896
|
|
|
893
897
|
const tempBuf = store.graphTempBuf[type];
|
|
894
898
|
|
|
@@ -956,7 +960,8 @@ function manageHistory(type, value) {
|
|
|
956
960
|
|
|
957
961
|
// Reset per il prossimo bucket
|
|
958
962
|
store.graphTempBuf[type] = [];
|
|
959
|
-
|
|
963
|
+
// Spostiamo il timer esattamente al confine del secchiello assoluto appena concluso
|
|
964
|
+
store.lastUpdates[type] = Math.floor(now / bucketIntervalMs) * bucketIntervalMs;
|
|
960
965
|
}
|
|
961
966
|
|
|
962
967
|
/**
|
|
@@ -1317,13 +1322,26 @@ function connect() {
|
|
|
1317
1322
|
let addr = window.location.host || CONFIG.server.fallbackIp;
|
|
1318
1323
|
try {
|
|
1319
1324
|
socket = new WebSocket(`ws://${addr}/signalk/v1/stream?subscribe=self`);
|
|
1320
|
-
|
|
1325
|
+
|
|
1326
|
+
socket.onopen = async () => {
|
|
1327
|
+
ui.status.className = "online";
|
|
1328
|
+
ui.status.innerText = "ONLINE";
|
|
1329
|
+
reconnectDelay = 1000;
|
|
1330
|
+
|
|
1331
|
+
// SINCRONIZZAZIONE AUTOMATICA: Ogni volta che la connessione si apre o si riapre,
|
|
1332
|
+
// scarichiamo lo storico fresco dal server e ridisegnamo i grafici
|
|
1333
|
+
try {
|
|
1334
|
+
await fetchServerHistory();
|
|
1335
|
+
['stw', 'sog', 'depth', 'tws'].forEach(refreshGraph);
|
|
1336
|
+
} catch (err) {
|
|
1337
|
+
console.warn("⚠️ Sincronizzazione storico fallita alla connessione:", err);
|
|
1338
|
+
}
|
|
1339
|
+
};
|
|
1321
1340
|
|
|
1322
1341
|
socket.onmessage = (e) => {
|
|
1323
1342
|
const d = JSON.parse(e.data);
|
|
1324
1343
|
if (d.updates) {
|
|
1325
1344
|
d.updates.forEach(u => {
|
|
1326
|
-
// ESTRAZIONE AVANZATA DELLA SORGENTE (Gestisce $source e stringhe native)
|
|
1327
1345
|
let sourceLabel = "Unknown";
|
|
1328
1346
|
if (u.$source) {
|
|
1329
1347
|
sourceLabel = u.$source;
|
|
@@ -1342,8 +1360,17 @@ function connect() {
|
|
|
1342
1360
|
}
|
|
1343
1361
|
};
|
|
1344
1362
|
|
|
1345
|
-
socket.onclose = () => {
|
|
1346
|
-
|
|
1363
|
+
socket.onclose = () => {
|
|
1364
|
+
if (!simulationMode) {
|
|
1365
|
+
ui.status.className = "offline";
|
|
1366
|
+
ui.status.innerText = "RECONNECTING...";
|
|
1367
|
+
setTimeout(connect, reconnectDelay);
|
|
1368
|
+
reconnectDelay = Math.min(reconnectDelay * 1.5, 10000);
|
|
1369
|
+
}
|
|
1370
|
+
};
|
|
1371
|
+
} catch (e) {
|
|
1372
|
+
setTimeout(connect, reconnectDelay);
|
|
1373
|
+
}
|
|
1347
1374
|
}
|
|
1348
1375
|
|
|
1349
1376
|
// ==========================================================================
|
|
@@ -1366,46 +1393,35 @@ window.addEventListener('contextmenu', e => e.preventDefault(), true);
|
|
|
1366
1393
|
async function init() {
|
|
1367
1394
|
loadDashboardState();
|
|
1368
1395
|
|
|
1369
|
-
//
|
|
1370
|
-
try {
|
|
1371
|
-
await fetchServerHistory();
|
|
1372
|
-
} catch (err) {
|
|
1373
|
-
console.warn("⚠️ Impossibile caricare lo storico dal server.");
|
|
1374
|
-
}
|
|
1375
|
-
|
|
1396
|
+
// Proviamo un primo caricamento configurazioni
|
|
1376
1397
|
await fetchServerConfig();
|
|
1377
1398
|
startDisplayLoop();
|
|
1378
|
-
connect();
|
|
1399
|
+
connect();
|
|
1379
1400
|
|
|
1380
1401
|
setInterval(watchConfigChanges, 10000);
|
|
1381
1402
|
|
|
1382
1403
|
// ==========================================================================
|
|
1383
|
-
//
|
|
1404
|
+
// RICONNESSIONE RAPIDA AL RISVEGLIO (VISIBILITY WATCHDOG)
|
|
1384
1405
|
// ==========================================================================
|
|
1385
1406
|
|
|
1386
|
-
//
|
|
1407
|
+
// Quando sblocchi l'iPad o riapri il browser, forziamo la chiusura del vecchio
|
|
1408
|
+
// WebSocket orfano. Questo farà scattare immediatamente connect() e la sincronizzazione.
|
|
1387
1409
|
document.addEventListener('visibilitychange', () => {
|
|
1388
1410
|
if (document.visibilityState === 'visible') {
|
|
1389
|
-
|
|
1411
|
+
console.log("⏰ Schermo sbloccato: forzatura riconnessione rapida.");
|
|
1412
|
+
if (socket) {
|
|
1413
|
+
try {
|
|
1414
|
+
socket.close(); // Fa scattare onclose -> connect() -> onopen -> fetchServerHistory()
|
|
1415
|
+
} catch (e) {
|
|
1416
|
+
connect();
|
|
1417
|
+
}
|
|
1418
|
+
} else {
|
|
1419
|
+
connect();
|
|
1420
|
+
}
|
|
1390
1421
|
}
|
|
1391
1422
|
});
|
|
1392
|
-
|
|
1393
|
-
// Rileva se il computer è andato in sospensione misurando il ritardo dei secondi
|
|
1394
|
-
let lastHeartbeat = Date.now();
|
|
1395
|
-
setInterval(() => {
|
|
1396
|
-
const now = Date.now();
|
|
1397
|
-
const diff = now - lastHeartbeat;
|
|
1398
|
-
lastHeartbeat = now;
|
|
1399
|
-
|
|
1400
|
-
// Se passano più di 6 secondi tra un ciclo e l'altro (invece di 1 secondo),
|
|
1401
|
-
// significa che il PC era in sospensione. Avviamo il risveglio.
|
|
1402
|
-
if (diff > 6000) {
|
|
1403
|
-
handleWakeUp();
|
|
1404
|
-
}
|
|
1405
|
-
}, 1000);
|
|
1406
1423
|
}
|
|
1407
1424
|
|
|
1408
1425
|
|
|
1409
|
-
|
|
1410
1426
|
window.addEventListener('load', init);
|
|
1411
1427
|
window.addEventListener('pagehide', saveDashboardState);
|
package/index.js
CHANGED
|
@@ -153,11 +153,15 @@ module.exports = function (app) {
|
|
|
153
153
|
const samples = 60;
|
|
154
154
|
const bucketIntervalMs = (historyMinutes * 60000) / samples;
|
|
155
155
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
if (!graphTempBuf[type]) graphTempBuf[type] = [];
|
|
157
|
+
if (!histories[type]) histories[type] = [];
|
|
158
|
+
|
|
159
|
+
// SINTONIZZAZIONE DI FASE LATO SERVER (UTC Snap)
|
|
160
|
+
if (lastUpdates[type] === undefined || lastUpdates[type] === 0) {
|
|
161
|
+
lastUpdates[type] = Math.floor(now / bucketIntervalMs) * bucketIntervalMs;
|
|
162
|
+
}
|
|
159
163
|
|
|
160
|
-
|
|
164
|
+
const tempBuf = graphTempBuf[type];
|
|
161
165
|
|
|
162
166
|
// Anti-dropout dinamico sul vento forte
|
|
163
167
|
if ((type === 'tws' || type === 'aws') && value < 0.05 && tempBuf.length > 0) {
|
|
@@ -219,9 +223,10 @@ module.exports = function (app) {
|
|
|
219
223
|
histories[type].shift();
|
|
220
224
|
}
|
|
221
225
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
226
|
+
graphTempBuf[type] = [];
|
|
227
|
+
// Spostiamo il timer esattamente al confine del secchiello assoluto appena concluso
|
|
228
|
+
lastUpdates[type] = Math.floor(now / bucketIntervalMs) * bucketIntervalMs;
|
|
229
|
+
}
|
|
225
230
|
|
|
226
231
|
/**
|
|
227
232
|
* plugin.schema: Definisce l'interfaccia grafica in Signal K Admin.
|