@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.
Files changed (3) hide show
  1. package/app.js +46 -19
  2. package/index.js +36 -18
  3. 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
- // 5. MOTORE DI CALCOLO VENTO E DATA ROUTING
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
- store.raw["environment.wind.speedTrue"] = tws_water;
339
- if (tws_water > 0.05) {
340
- const twa = Math.atan2(tw_water_y, tw_water_x);
341
- store.raw["environment.wind.angleTrueWater"] = twa;
342
- safePush(store.smoothBuf.twa, twa, now); safePush(store.longBuf.twa, twa, now);
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
- if (tws_ground > 0.05) {
345
- let twd = (hdg + Math.atan2(tw_ground_y, tw_ground_x) + 2 * Math.PI) % (2 * Math.PI);
346
- store.raw["environment.wind.directionTrue"] = twd;
347
- safePush(store.smoothBuf.twd, twd, now); safePush(store.longBuf.twd, twd, now);
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
- // Elaborazione e invio alla macchina a stati temporali dello storico
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 del Vento Reale (TWS) e della VMG a livello Server
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
- const awsKts = aws * 1.94384;
132
- const stwKts = stw * 1.94384;
133
- const tw_water_x = awsKts * Math.cos(awa) - stwKts;
134
- const tw_water_y = awsKts * Math.sin(awa);
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
- const twa = Math.atan2(tw_water_y, tw_water_x);
140
- const vmg = Math.abs(stwKts * Math.cos(twa));
141
- manageHistory('vmg', vmg);
142
-
143
- // --- CALCOLO TWD STRATEGICO SERVER-SIDE ---
144
- if (hdg !== undefined) {
145
- // Calcolo della direzione del vento reale rispetto al nord (TWD) in radianti
146
- const twd = (hdg + twa + 2 * Math.PI) % (2 * Math.PI);
147
- manageHistory('twd', twd);
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
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sailingrotevista/rotevista-dash",
3
- "version": "6.1.2",
3
+ "version": "6.1.3",
4
4
  "description": "Wind Dashboard with navigation and course aids",
5
5
  "main": "index.js",
6
6
  "publishConfig": {