@sailingrotevista/rotevista-dash 7.0.11 → 7.0.13

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 CHANGED
@@ -23,7 +23,7 @@ let CONFIG = {
23
23
  minSpeed: 0.5,
24
24
  stabilityBreakout: 15
25
25
  },
26
- graphs: { reef1: 5, reef2: 10, historyMinutes: 10, samples: 60 },
26
+ graphs: { reef1: 10, reef2: 15, 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 },
@@ -210,18 +210,23 @@ function checkDepthAlarm(m) {
210
210
  }
211
211
 
212
212
  /**
213
- * computeTrueWind: Calcola TWS, TWA e TWD strategico.
214
- * Gestisce il fallback separato (Split-Fallback) in caso di dati parzialmente nativi di bordo.
215
- */
213
+ * computeTrueWind: Calcola TWS, TWA e TWD strategico.
214
+ * Gestisce il fallback separato (Split-Fallback) in caso di dati parzialmente nativi di bordo.
215
+ */
216
216
  function computeTrueWind() {
217
217
  const aws = store.raw["environment.wind.speedApparent"], awa = store.raw["environment.wind.angleApparent"];
218
- const stw = store.raw["navigation.speedThroughWater"] || 0, sog = store.raw["navigation.speedOverGround"] || 0;
218
+ const stw = store.raw["navigation.speedThroughWater"], sog = store.raw["navigation.speedOverGround"] || 0;
219
219
  const hdg = store.raw["navigation.headingTrue"] || 0, cog = store.raw["navigation.courseOverGroundTrue"] || 0;
220
220
  if (aws === undefined || awa === undefined) return;
221
221
 
222
222
  // Usiamo il tempo esatto di arrivo del pacchetto del vento per la coerenza dei buffer
223
223
  const now = store.timestamps["environment.wind.speedApparent"] || Date.now();
224
224
 
225
+ // Verifica se lo STW fisicamente attivo ha trasmesso dati negli ultimi 15 secondi
226
+ const hasStw = store.timestamps["navigation.speedThroughWater"] && (now - store.timestamps["navigation.speedThroughWater"] < 15000);
227
+ // Se lo STW non è disponibile, usa automaticamente la velocità del GPS (SOG) come riferimento
228
+ const speedRef = hasStw && stw !== undefined ? stw : sog;
229
+
225
230
  // ==========================================================================
226
231
  // 1. GESTIONE TWS (NATIVO vs FALLBACK)
227
232
  // ==========================================================================
@@ -232,14 +237,14 @@ function computeTrueWind() {
232
237
  // Se la barca invia il TWS nativo, usiamo direttamente quello
233
238
  tws_water = store.raw["environment.wind.speedTrue"] ? msToKts(store.raw["environment.wind.speedTrue"]) : 0;
234
239
  } else {
235
- // Altrimenti eseguiamo il calcolo vettoriale tattico sull'acqua
236
- tws_water = Math.sqrt(aws * aws + stw * stw - 2 * aws * stw * Math.cos(awa));
240
+ // Altrimenti eseguiamo il calcolo vettoriale tattico utilizzando la velocità di riferimento (STW o SOG)
241
+ tws_water = Math.sqrt(aws * aws + speedRef * speedRef - 2 * aws * speedRef * Math.cos(awa));
237
242
  store.raw["environment.wind.speedTrue"] = tws_water;
238
243
  }
239
244
 
240
245
  // BUG RISOLTO: Calcoliamo il TWA sempre, indipendentemente dal TWS nativo!
241
246
  if (tws_water > 0.05) {
242
- const twa = Math.atan2(aws * Math.sin(awa), aws * Math.cos(awa) - stw);
247
+ const twa = Math.atan2(aws * Math.sin(awa), aws * Math.cos(awa) - speedRef);
243
248
  store.raw["environment.wind.angleTrueWater"] = twa;
244
249
 
245
250
  // Inserimento atomico e sincronizzato di TWA e AWA nei relativi buffer mobili
@@ -523,10 +528,10 @@ function updateWindTrend() {
523
528
  }
524
529
  if (deltaTac > 0) {
525
530
  if (gaugeDots.cw) { gaugeDots.cw.classList.add('is-trending'); gaugeDots.cw.setAttribute('fill', tacticColor); }
526
- if (gaugeDots.ccw) { gaugeDots.ccw.classList.remove('is-trending'); }
531
+ if (gaugeDots.ccw) { gaugeDots.ccw.classList.remove('is-trending'); gaugeDots.ccw.setAttribute('fill', '#bbb'); } // Resetta l'attributo di riempimento del pallino inattivo
527
532
  } else {
528
533
  if (gaugeDots.ccw) { gaugeDots.ccw.classList.add('is-trending'); gaugeDots.ccw.setAttribute('fill', tacticColor); }
529
- if (gaugeDots.cw) { gaugeDots.cw.classList.remove('is-trending'); }
534
+ if (gaugeDots.cw) { gaugeDots.cw.classList.remove('is-trending'); gaugeDots.cw.setAttribute('fill', '#bbb'); } // Resetta l'attributo di riempimento del pallino inattivo
530
535
  }
531
536
  } else {
532
537
  [gaugeDots.cw, gaugeDots.ccw].forEach(el => { if(el){ el.classList.remove('is-trending'); el.setAttribute('fill', '#bbb'); }});
package/index.js CHANGED
@@ -252,15 +252,20 @@ module.exports = function (app) {
252
252
  // 2. Calcolo combinato di FALLBACK (Si attiva solo se la centralina non invia TWS/TWD nativi)
253
253
  const aws = raw["environment.wind.speedApparent"];
254
254
  const awa = raw["environment.wind.angleApparent"];
255
- const stw = raw["navigation.speedThroughWater"] || 0;
255
+ const stw = raw["navigation.speedThroughWater"];
256
256
  const sog = raw["navigation.speedOverGround"] || 0;
257
257
  const hdg = raw["navigation.headingTrue"];
258
258
  const cog = raw["navigation.courseOverGroundTrue"] || 0;
259
259
 
260
260
  if (aws !== undefined && awa !== undefined) {
261
261
  const awsKts = aws * 1.94384;
262
- const stwKts = stw * 1.94384;
263
- const tw_water_x = awsKts * Math.cos(awa) - stwKts;
262
+
263
+ // Verifica se lo STW fisicamente attivo ha trasmesso dati negli ultimi 15 secondi
264
+ const hasStw = lastPathProcessTimes["navigation.speedThroughWater"] && (now - lastPathProcessTimes["navigation.speedThroughWater"] < 15000);
265
+ // Se lo STW non è disponibile, usa automaticamente la velocità del GPS (SOG) come riferimento
266
+ const speedKtsRef = hasStw && stw !== undefined ? (stw * 1.94384) : (sog * 1.94384);
267
+
268
+ const tw_water_x = awsKts * Math.cos(awa) - speedKtsRef;
264
269
  const tw_water_y = awsKts * Math.sin(awa);
265
270
 
266
271
  // Calcoliamo il TWS di fallback solo se non abbiamo visto dati nativi negli ultimi 5 secondi
@@ -271,8 +276,8 @@ module.exports = function (app) {
271
276
 
272
277
  const twa = Math.atan2(tw_water_y, tw_water_x);
273
278
 
274
- // La VMG viene sempre calcolata a livello server poiché raramente è nativa
275
- const vmg = Math.abs(stwKts * Math.cos(twa));
279
+ // La VMG viene calcolata usando la velocità di riferimento (STW reale o SOG di fallback)
280
+ const vmg = Math.abs(speedKtsRef * Math.cos(twa));
276
281
  manageHistory('vmg', vmg);
277
282
 
278
283
  // Calcoliamo il TWD di fallback solo se non abbiamo visto dati nativi negli ultimi 5 secondi
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sailingrotevista/rotevista-dash",
3
- "version": "7.0.11",
3
+ "version": "7.0.13",
4
4
  "description": "Wind Dashboard with navigation and course aids",
5
5
  "main": "index.js",
6
6
  "publishConfig": {
package/style.css CHANGED
@@ -385,7 +385,7 @@ body.night-mode .alarm-danger {
385
385
 
386
386
  /* ==========================================================================
387
387
  9. WIDGETS E OVERRIDE SVG (GIORNO)
388
- ========================================================================== */
388
+ ========================================================================= */
389
389
  #status {
390
390
  position: absolute;
391
391
  top: 15px; right: 15px;
@@ -463,8 +463,46 @@ body.night-mode {
463
463
  .night-mode .is-focused .scale-labels { color: #ff3333 !important; }
464
464
 
465
465
  /* --- 10.4 WIND GAUGE (STRUMENTO CENTRALE) --- */
466
- .night-mode #wind-gauge circle { fill: #000 !important; stroke: #220000 !important; }
467
- .night-mode #wind-gauge circle:nth-of-type(2), .night-mode #fullscreen-hotspot { fill: #050000 !important; stroke: #330000 !important; }
466
+ .night-mode #wind-gauge circle:not(#trend-gauge-cw):not(#trend-gauge-ccw) {
467
+ fill: #000000 !important;
468
+ stroke: #220000 !important;
469
+ }
470
+ .night-mode #wind-gauge > circle:nth-of-type(2), .night-mode #fullscreen-hotspot {
471
+ fill: #050000 !important;
472
+ stroke: #330000 !important;
473
+ }
474
+
475
+ /* 1. STATO SPENTO/RIPOSO: Attivo solo se l'attributo fill originario è grigio (#bbb o #bbbbbb) */
476
+ .night-mode #trend-gauge-cw[fill="#bbb"],
477
+ .night-mode #trend-gauge-ccw[fill="#bbb"],
478
+ .night-mode #trend-gauge-cw[fill="#bbbbbb"],
479
+ .night-mode #trend-gauge-ccw[fill="#bbbbbb"] {
480
+ fill: #440000 !important; /* Rosso scurissimo soffuso */
481
+ stroke: none !important;
482
+ filter: none !important;
483
+ opacity: 0.3 !important;
484
+ }
485
+
486
+ /* 2. STATO ATTIVO VERDE (Buono/Sotto-vento): Attivo solo se JS imposta il colore di lift (#27ae60) */
487
+ .night-mode #trend-gauge-cw[fill="#27ae60"],
488
+ .night-mode #trend-gauge-ccw[fill="#27ae60"] {
489
+ fill: #00C851 !important; /* Verde smeraldo brillante */
490
+ stroke: none !important;
491
+ filter: drop-shadow(0 0 5px #00C851) !important;
492
+ opacity: 1 !important;
493
+ }
494
+
495
+ /* 3. STATO ATTIVO ROSSO (Scarso/Sopra-vento o strambata): Attivo se JS imposta il colore di header (#c0392b) o se in allarme strambata */
496
+ .night-mode #trend-gauge-cw[fill="#c0392b"],
497
+ .night-mode #trend-gauge-ccw[fill="#c0392b"],
498
+ .night-mode #trend-gauge-cw.is-gybing,
499
+ .night-mode #trend-gauge-ccw.is-gybing {
500
+ fill: #ff3b30 !important; /* Rosso brillante */
501
+ stroke: none !important;
502
+ filter: drop-shadow(0 0 5px #ff3b30) !important;
503
+ opacity: 1 !important;
504
+ }
505
+
468
506
  .night-mode #center-glow feDropShadow { flood-color: #ff0000 !important; flood-opacity: 0.6 !important; }
469
507
  .night-mode #boat-icon { fill: #220000 !important; stroke: #ff0000 !important; stroke-width: 0.8px !important; opacity: 1 !important; }
470
508
  .night-mode #aws-display-group text { fill: #800000 !important; }
@@ -490,10 +528,16 @@ body.night-mode {
490
528
  .night-mode #twd-boat-wrap path { fill: #ff3333 !important; opacity: 0.4 !important; }
491
529
  .night-mode #twd-arrow #twd-wind-chevron { stroke: #ff3333 !important; }
492
530
 
493
- /* --- 10.6 LOGICA RED-SHIFT TREND --- */
494
- .night-mode circle[fill="#bbb"], .night-mode circle[fill="#bbbbbb"] { fill: #440000 !important; }
495
- .night-mode circle[fill="#27ae60"] { fill: #ff0000 !important; }
496
- .night-mode circle[fill="#c0392b"] { fill: #800000 !important; }
531
+ /* --- 10.6 LOGICA RED-SHIFT TREND (PULITA) --- */
532
+ .night-mode circle[fill="#bbb"]:not(#trend-gauge-cw):not(#trend-gauge-ccw), .night-mode circle[fill="#bbbbbb"]:not(#trend-gauge-cw):not(#trend-gauge-ccw) {
533
+ fill: #440000 !important;
534
+ }
535
+ .night-mode circle[fill="#27ae60"]:not(#trend-gauge-cw):not(#trend-gauge-ccw) {
536
+ fill: #ff0000 !important;
537
+ }
538
+ .night-mode circle[fill="#c0392b"]:not(#trend-gauge-cw):not(#trend-gauge-ccw) {
539
+ fill: #800000 !important;
540
+ }
497
541
 
498
542
  /* ==========================================================================
499
543
  11. TREND E ANIMAZIONI
@@ -533,11 +577,11 @@ body.night-mode {
533
577
  }
534
578
 
535
579
  /* --- OVERRIDE NIGHT MODE PER IL WIND RADAR --- */
536
- .night-mode #wind-radar circle {
580
+ .night-mode #wind-radar circle:not(.is-trending) {
537
581
  fill: #000000 !important;
538
582
  stroke: #220000 !important;
539
583
  }
540
- .night-mode #wind-radar circle:nth-of-type(2),
584
+ .night-mode #wind-radar circle:nth-of-type(2):not(.is-trending),
541
585
  .night-mode #radar-hotspot {
542
586
  fill: #050000 !important;
543
587
  stroke: #330000 !important;
package/weather-radar.js CHANGED
@@ -238,6 +238,16 @@ function renderRadar() {
238
238
  borderPath.setAttribute("stroke-linecap", "round");
239
239
  borderPath.setAttribute("opacity", opacityValue);
240
240
  ringsContainer.appendChild(borderPath);
241
+ } else {
242
+ const borderPath = document.createElementNS("http://www.w3.org/2000/svg", "path");
243
+ borderPath.setAttribute("d", pathData);
244
+ borderPath.setAttribute("fill", "none");
245
+ const isNight = document.body.classList.contains('night-mode');
246
+ borderPath.setAttribute("stroke", isNight ? "#220000" : "#90a4ae");
247
+ borderPath.setAttribute("stroke-width", BORDER_STROKE_WIDTH);
248
+ borderPath.setAttribute("stroke-linecap", "round");
249
+ borderPath.setAttribute("opacity", "0.6");
250
+ ringsContainer.appendChild(borderPath);
241
251
  }
242
252
 
243
253
  const mainPath = document.createElementNS("http://www.w3.org/2000/svg", "path");
@@ -246,7 +256,7 @@ function renderRadar() {
246
256
  mainPath.setAttribute("stroke", strokeColor);
247
257
  mainPath.setAttribute("stroke-width", ARC_STROKE_WIDTH);
248
258
  mainPath.setAttribute("stroke-linecap", "round");
249
- mainPath.setAttribute("opacity", data.isFuture ? "0.5" : opacityValue);
259
+ mainPath.setAttribute("opacity", data.isFuture ? "0.7" : opacityValue);
250
260
  mainPath.id = data.isFuture ? "" : (index === 1 ? "active-present-arc" : "");
251
261
  ringsContainer.appendChild(mainPath);
252
262
  });