@sailingrotevista/rotevista-dash 6.1.2 → 6.1.3
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 +46 -19
- package/index.js +36 -18
- package/package.json +1 -1
package/app.js
CHANGED
|
@@ -317,34 +317,61 @@ function updateLeewayDisplay(deg) {
|
|
|
317
317
|
ui.leewayVal.textContent = `LEEWAY: ${deg.toFixed(1)}°`;
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
320
|
+
/**
|
|
321
|
+
* computeTrueWind: Calcola TWS, TWA e TWD strategico.
|
|
322
|
+
* Gestisce il fallback separato (Split-Fallback) in caso di dati parzialmente nativi di bordo.
|
|
323
|
+
*/
|
|
323
324
|
function computeTrueWind() {
|
|
324
325
|
const aws = store.raw["environment.wind.speedApparent"], awa = store.raw["environment.wind.angleApparent"];
|
|
325
326
|
const stw = store.raw["navigation.speedThroughWater"] || 0, sog = store.raw["navigation.speedOverGround"] || 0;
|
|
326
327
|
const hdg = store.raw["navigation.headingTrue"] || 0, cog = store.raw["navigation.courseOverGroundTrue"] || 0;
|
|
327
328
|
if (aws === undefined || awa === undefined) return;
|
|
328
329
|
|
|
329
|
-
const tw_water_x = aws * Math.cos(awa) - stw, tw_water_y = aws * Math.sin(awa);
|
|
330
|
-
const tws_water = Math.sqrt(tw_water_x * tw_water_x + tw_water_y * tw_water_y);
|
|
331
|
-
|
|
332
|
-
const drift = (cog - hdg + Math.PI * 3) % (2 * Math.PI) - Math.PI;
|
|
333
|
-
const tw_ground_x = aws * Math.cos(awa) - sog * Math.cos(drift), tw_ground_y = aws * Math.sin(awa) - sog * Math.sin(drift);
|
|
334
|
-
const tws_ground = Math.sqrt(tw_ground_x * tw_ground_x + tw_ground_y * tw_ground_y);
|
|
335
|
-
|
|
336
330
|
// Usiamo il tempo esatto di arrivo del pacchetto del vento per la coerenza dei buffer
|
|
337
331
|
const now = store.timestamps["environment.wind.speedApparent"] || Date.now();
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
332
|
+
|
|
333
|
+
// ==========================================================================
|
|
334
|
+
// 1. GESTIONE TWS (NATIVO vs FALLBACK)
|
|
335
|
+
// ==========================================================================
|
|
336
|
+
const hasNativeTws = store.timestamps["environment.wind.speedTrue"] && (Date.now() - store.timestamps["environment.wind.speedTrue"] < 5000);
|
|
337
|
+
let tws_water = 0;
|
|
338
|
+
|
|
339
|
+
if (hasNativeTws) {
|
|
340
|
+
// Se la barca invia il TWS nativo, usiamo direttamente quello
|
|
341
|
+
tws_water = store.raw["environment.wind.speedTrue"] ? msToKts(store.raw["environment.wind.speedTrue"]) : 0;
|
|
342
|
+
} else {
|
|
343
|
+
// Altrimenti eseguiamo il calcolo vettoriale tattico sull'acqua
|
|
344
|
+
tws_water = Math.sqrt(aws * aws + stw * stw - 2 * aws * stw * Math.cos(awa));
|
|
345
|
+
store.raw["environment.wind.speedTrue"] = tws_water;
|
|
346
|
+
|
|
347
|
+
if (tws_water > 0.05) {
|
|
348
|
+
const twa = Math.atan2(aws * Math.sin(awa), aws * Math.cos(awa) - stw);
|
|
349
|
+
store.raw["environment.wind.angleTrueWater"] = twa;
|
|
350
|
+
safePush(store.smoothBuf.twa, twa, now);
|
|
351
|
+
safePush(store.longBuf.twa, twa, now);
|
|
352
|
+
}
|
|
343
353
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
354
|
+
|
|
355
|
+
// ==========================================================================
|
|
356
|
+
// 2. GESTIONE TWD (NATIVO vs FALLBACK)
|
|
357
|
+
// ==========================================================================
|
|
358
|
+
const hasNativeTwd = store.timestamps["environment.wind.directionTrue"] && (Date.now() - store.timestamps["environment.wind.directionTrue"] < 5000);
|
|
359
|
+
|
|
360
|
+
if (hasNativeTwd) {
|
|
361
|
+
// Se il TWD è nativo della centralina, lo lasciamo scorrere passivamente
|
|
362
|
+
} else {
|
|
363
|
+
// Altrimenti calcoliamo lo scarroccio e ricaviamo il TWD geografico sul fondo
|
|
364
|
+
const drift = (cog - hdg + Math.PI * 3) % (2 * Math.PI) - Math.PI;
|
|
365
|
+
const tw_ground_x = aws * Math.cos(awa) - sog * Math.cos(drift);
|
|
366
|
+
const tw_ground_y = aws * Math.sin(awa) - sog * Math.sin(drift);
|
|
367
|
+
const tws_ground = Math.sqrt(tw_ground_x * tw_ground_x + tw_ground_y * tw_ground_y);
|
|
368
|
+
|
|
369
|
+
if (tws_ground > 0.05) {
|
|
370
|
+
let twd = (hdg + Math.atan2(tw_ground_y, tw_ground_x) + 2 * Math.PI) % (2 * Math.PI);
|
|
371
|
+
store.raw["environment.wind.directionTrue"] = twd;
|
|
372
|
+
safePush(store.smoothBuf.twd, twd, now);
|
|
373
|
+
safePush(store.longBuf.twd, twd, now); // Alimenta la bussola meteo strategica!
|
|
374
|
+
}
|
|
348
375
|
}
|
|
349
376
|
}
|
|
350
377
|
|
package/index.js
CHANGED
|
@@ -21,6 +21,9 @@ module.exports = function (app) {
|
|
|
21
21
|
let graphTempBuf = { stw: [], sog: [], depth: [], tws: [], vmg: [], aws: [], twd: [] };
|
|
22
22
|
let lastUpdates = { stw: 0, sog: 0, depth: 0, tws: 0, vmg: 0, aws: 0, twd: 0 };
|
|
23
23
|
let raw = {};
|
|
24
|
+
// Memoria temporale per rilevare la presenza di sensori nativi sul Cerbo
|
|
25
|
+
let lastNativeTwsTime = 0;
|
|
26
|
+
let lastNativeTwdTime = 0;
|
|
24
27
|
|
|
25
28
|
/**
|
|
26
29
|
* plugin.start: Inizializza il plugin.
|
|
@@ -98,14 +101,17 @@ module.exports = function (app) {
|
|
|
98
101
|
app.debug(msg);
|
|
99
102
|
};
|
|
100
103
|
|
|
101
|
-
|
|
104
|
+
/**
|
|
102
105
|
* processIncomingDelta: Decodifica i dati dei sensori in Knots/Meters ed esegue l'aggregazione
|
|
106
|
+
* Gestisce l'architettura "Nativo Prima, Fallback Dopo" per il vento reale.
|
|
103
107
|
*/
|
|
104
108
|
function processIncomingDelta(path, val) {
|
|
105
109
|
if (val === null || val === undefined) return;
|
|
106
110
|
raw[path] = val;
|
|
107
111
|
|
|
108
|
-
|
|
112
|
+
const now = Date.now();
|
|
113
|
+
|
|
114
|
+
// 1. Cattura dei dati nativi (Se presenti, li scrive direttamente nello storico)
|
|
109
115
|
if (path === 'navigation.speedThroughWater') {
|
|
110
116
|
manageHistory('stw', val * 1.94384);
|
|
111
117
|
}
|
|
@@ -118,8 +124,16 @@ module.exports = function (app) {
|
|
|
118
124
|
else if (path === 'environment.wind.speedApparent') {
|
|
119
125
|
manageHistory('aws', val * 1.94384);
|
|
120
126
|
}
|
|
127
|
+
else if (path === 'environment.wind.speedTrue') {
|
|
128
|
+
lastNativeTwsTime = now; // Rilevato TWS nativo della centralina!
|
|
129
|
+
manageHistory('tws', val * 1.94384);
|
|
130
|
+
}
|
|
131
|
+
else if (path === 'environment.wind.directionTrue') {
|
|
132
|
+
lastNativeTwdTime = now; // Rilevato TWD nativo della centralina!
|
|
133
|
+
manageHistory('twd', val);
|
|
134
|
+
}
|
|
121
135
|
|
|
122
|
-
// Calcolo combinato
|
|
136
|
+
// 2. Calcolo combinato di FALLBACK (Si attiva solo se la centralina non invia TWS/TWD nativi)
|
|
123
137
|
const aws = raw["environment.wind.speedApparent"];
|
|
124
138
|
const awa = raw["environment.wind.angleApparent"];
|
|
125
139
|
const stw = raw["navigation.speedThroughWater"] || 0;
|
|
@@ -128,25 +142,29 @@ module.exports = function (app) {
|
|
|
128
142
|
const cog = raw["navigation.courseOverGroundTrue"] || 0;
|
|
129
143
|
|
|
130
144
|
if (aws !== undefined && awa !== undefined) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const tws = Math.sqrt(tw_water_x * tw_water_x + tw_water_y * tw_water_y);
|
|
145
|
+
const awsKts = aws * 1.94384;
|
|
146
|
+
const stwKts = stw * 1.94384;
|
|
147
|
+
const tw_water_x = awsKts * Math.cos(awa) - stwKts;
|
|
148
|
+
const tw_water_y = awsKts * Math.sin(awa);
|
|
136
149
|
|
|
150
|
+
// Calcoliamo il TWS di fallback solo se non abbiamo visto dati nativi negli ultimi 5 secondi
|
|
151
|
+
if (now - lastNativeTwsTime > 5000) {
|
|
152
|
+
const tws = Math.sqrt(tw_water_x * tw_water_x + tw_water_y * tw_water_y);
|
|
137
153
|
manageHistory('tws', tws);
|
|
154
|
+
}
|
|
138
155
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
156
|
+
const twa = Math.atan2(tw_water_y, tw_water_x);
|
|
157
|
+
|
|
158
|
+
// La VMG viene sempre calcolata a livello server poiché raramente è nativa
|
|
159
|
+
const vmg = Math.abs(stwKts * Math.cos(twa));
|
|
160
|
+
manageHistory('vmg', vmg);
|
|
161
|
+
|
|
162
|
+
// Calcoliamo il TWD di fallback solo se non abbiamo visto dati nativi negli ultimi 5 secondi
|
|
163
|
+
if (hdg !== undefined && (now - lastNativeTwdTime > 5000)) {
|
|
164
|
+
const twd = (hdg + twa + 2 * Math.PI) % (2 * Math.PI);
|
|
165
|
+
manageHistory('twd', twd);
|
|
149
166
|
}
|
|
167
|
+
}
|
|
150
168
|
}
|
|
151
169
|
|
|
152
170
|
/**
|