@sailingrotevista/rotevista-dash 7.0.3 → 7.0.6
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 +18 -1
- package/charts.js +24 -19
- package/index.js +19 -19
- package/package.json +1 -1
package/app.js
CHANGED
|
@@ -23,7 +23,7 @@ let CONFIG = {
|
|
|
23
23
|
minSpeed: 0.5,
|
|
24
24
|
stabilityBreakout: 15
|
|
25
25
|
},
|
|
26
|
-
graphs: { reef1:
|
|
26
|
+
graphs: { reef1: 5, reef2: 10, historyMinutes: 10, samples: 60 },
|
|
27
27
|
scales: {
|
|
28
28
|
stw: { stdMax: 4, hercSpan: 2, step: 1 },
|
|
29
29
|
sog: { stdMax: 4, hercSpan: 2, step: 1 },
|
|
@@ -47,6 +47,7 @@ let displayModeTws = 'TWS';
|
|
|
47
47
|
let activeInstrument = 'gauge'; // Modalità di default all'avvio: 'gauge' (analogico) o 'radar' (storico)
|
|
48
48
|
let socket, renderInterval, simInterval;
|
|
49
49
|
let lastAvgUIUpdate = 0; // Chirurgico: Rimosse audioCtx e lastAlarmTime poiché sono già dichiarate in utils.js
|
|
50
|
+
const lastPathProcessTimes = {}; // Registro dei timestamp per limitazione di frequenza client-side a 1Hz
|
|
50
51
|
|
|
51
52
|
let rotationTrend = 0, meteoTrend = 0;
|
|
52
53
|
let lastShortAvgVal = null, lastInstantTwa = null;
|
|
@@ -320,9 +321,25 @@ function processIncomingData(path, val, source, timeMs) {
|
|
|
320
321
|
}
|
|
321
322
|
}
|
|
322
323
|
|
|
324
|
+
// Aggiorna sempre lo stato raw istantaneo all'ultimo millisecondo per massimizzare la precisione digitale
|
|
323
325
|
store.timestamps[path] = now;
|
|
324
326
|
store.raw[path] = val;
|
|
325
327
|
|
|
328
|
+
// Le coordinate GPS e la posizione non sono soggette alla limitazione a 1Hz
|
|
329
|
+
if (path === "navigation.position") {
|
|
330
|
+
return; // Esce subito (non richiede calcoli trigonometrici o inserimenti in smoothBuf/longBuf)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// LIMITATORE DI FREQUENZA (RATE LIMITER) CLIENT-SIDE A 1HZ PER PERCORSO ATTIVO:
|
|
334
|
+
// Evita di eseguire calcoli trigonometrici, allocare oggetti in memoria dinamica
|
|
335
|
+
// e popolare i buffer smoothBuf/longBuf decine di volte al secondo per singolo sensore.
|
|
336
|
+
if (!lastPathProcessTimes[path]) lastPathProcessTimes[path] = 0;
|
|
337
|
+
if (now - lastPathProcessTimes[path] < 1000) {
|
|
338
|
+
return; // Esce subito risparmiando cicli di calcolo del browser e batteria del tablet
|
|
339
|
+
}
|
|
340
|
+
lastPathProcessTimes[path] = now;
|
|
341
|
+
|
|
342
|
+
// Da qui in poi, l'inserimento nei buffer fisici avviene rigorosamente a 1Hz:
|
|
326
343
|
if (path === "environment.wind.angleApparent") {
|
|
327
344
|
safePush(store.smoothBuf.awa, val, now);
|
|
328
345
|
safePush(store.longBuf.awa, val, now);
|
package/charts.js
CHANGED
|
@@ -179,25 +179,30 @@ function drawGraph(d, id, min, max, isTws, isHercules) {
|
|
|
179
179
|
const colDepth = "#0088cc", colStw = "#00C851", colSog = "#ffbb33", colVmg = "#00b8d4";
|
|
180
180
|
|
|
181
181
|
const getColorProps = (val) => {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
|
|
182
|
+
const baseStroke = isFocused ? "4.2" : "1.6";
|
|
183
|
+
const alertStroke = isFocused ? "4.8" : "2.2";
|
|
184
|
+
const warnStroke = isFocused ? "4.4" : "1.8";
|
|
185
|
+
|
|
186
|
+
let color = colTws, opacity = "0.15", stroke = baseStroke;
|
|
187
|
+
if (isTws) {
|
|
188
|
+
const baseWind = (displayModeTws === 'AWS') ? colAws : colTws;
|
|
189
|
+
const r1 = CONFIG.graphs.reef1 || 15;
|
|
190
|
+
const r2 = CONFIG.graphs.reef2 || 20;
|
|
191
|
+
const r3 = r2 + (r2 - r1); // Calcolo sintetico del 3° Terzarolo (Storm)
|
|
192
|
+
|
|
193
|
+
if (val >= r3) { color = "#9c27b0"; opacity = "0.65"; stroke = alertStroke; } // Viola (Tempesta / 3a Mano)
|
|
194
|
+
else if (val >= r2) { color = colDanger; opacity = "0.55"; stroke = alertStroke; } // Rosso (Pericolo / 2a Mano)
|
|
195
|
+
else if (val >= r1) { color = colWarning; opacity = "0.45"; stroke = warnStroke; } // Arancione (Allerta / 1a Mano)
|
|
196
|
+
else color = baseWind;
|
|
197
|
+
} else if (isDepth) {
|
|
198
|
+
if (val < CONFIG.alarms.depthDanger) { color = colDanger; opacity = "0.55"; stroke = alertStroke; }
|
|
199
|
+
else if (val < CONFIG.alarms.depthWarning) { color = colWarning; opacity = "0.45"; stroke = warnStroke; }
|
|
200
|
+
else color = colDepth;
|
|
201
|
+
} else {
|
|
202
|
+
if (id === 'stw-graph') color = colStw;
|
|
203
|
+
else if (id === 'sog-graph') color = (displayModeSog === 'VMG') ? colVmg : colSog;
|
|
204
|
+
}
|
|
205
|
+
return { color, opacity, stroke };
|
|
201
206
|
};
|
|
202
207
|
|
|
203
208
|
let grids = "";
|
package/index.js
CHANGED
|
@@ -85,24 +85,24 @@ module.exports = function (app) {
|
|
|
85
85
|
app.debug('Public API endpoints registered at /rotevista-config and /rotevista-history');
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
88
|
+
// 3. Iscrizione ai dati dei sensori di bordo tramite Signal K (Ottimizzata a 1Hz)
|
|
89
|
+
const localSubscription = {
|
|
90
|
+
context: 'vessels.self',
|
|
91
|
+
subscribe: [
|
|
92
|
+
{ path: 'navigation.position', minPeriod: 1000 },
|
|
93
|
+
{ path: 'navigation.speedThroughWater', minPeriod: 1000 },
|
|
94
|
+
{ path: 'navigation.speedOverGround', minPeriod: 1000 },
|
|
95
|
+
{ path: 'environment.depth.belowTransducer', minPeriod: 1000 },
|
|
96
|
+
{ path: 'environment.wind.speedApparent', minPeriod: 1000 },
|
|
97
|
+
{ path: 'environment.wind.angleApparent', minPeriod: 1000 },
|
|
98
|
+
{ path: 'environment.wind.speedTrue', minPeriod: 1000 },
|
|
99
|
+
{ path: 'environment.wind.directionTrue', minPeriod: 1000 },
|
|
100
|
+
{ path: 'navigation.headingTrue', minPeriod: 1000 },
|
|
101
|
+
{ path: 'navigation.headingMagnetic', minPeriod: 1000 },
|
|
102
|
+
{ path: 'navigation.magneticVariation', minPeriod: 1000 },
|
|
103
|
+
{ path: 'navigation.courseOverGroundTrue', minPeriod: 1000 }
|
|
104
|
+
]
|
|
105
|
+
};
|
|
106
106
|
|
|
107
107
|
app.subscriptionmanager.subscribe(
|
|
108
108
|
localSubscription,
|
|
@@ -145,7 +145,7 @@ module.exports = function (app) {
|
|
|
145
145
|
if (val === null || val === undefined) return;
|
|
146
146
|
|
|
147
147
|
const now = Date.now();
|
|
148
|
-
const alpha = 0
|
|
148
|
+
const alpha = 1.0; // Passa-tutto istantaneo (i sensori di bordo ST60+ sono già calibrati con damping hardware a 12)
|
|
149
149
|
|
|
150
150
|
// FILTRO PASSA-BASSO CONTINUO IN TEMPO REALE (Previene gli Spike prima della storicizzazione)
|
|
151
151
|
if (path === 'navigation.position') {
|