@sailingrotevista/rotevista-dash 7.0.32 → 7.0.34
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 +65 -58
- package/package.json +1 -1
package/app.js
CHANGED
|
@@ -377,17 +377,25 @@ function processIncomingData(path, val, source, timeMs) {
|
|
|
377
377
|
store.timestamps[path] = now;
|
|
378
378
|
store.raw[path] = val;
|
|
379
379
|
|
|
380
|
+
// Converte e aggiorna istantaneamente store.raw["navigation.headingTrue"] prima del rate limiter per evitare ritardi UI
|
|
381
|
+
if (path === "navigation.headingMagnetic") {
|
|
382
|
+
const hasNativeTrueHdg = store.timestamps["navigation.headingTrueNative"] && (now - store.timestamps["navigation.headingTrueNative"] < 5000);
|
|
383
|
+
if (!hasNativeTrueHdg) {
|
|
384
|
+
const variation = store.raw["navigation.magneticVariation"] || 0;
|
|
385
|
+
store.raw["navigation.headingTrue"] = (val + variation + 2 * Math.PI) % (2 * Math.PI);
|
|
386
|
+
store.timestamps["navigation.headingTrue"] = now;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
380
390
|
// Le coordinate GPS e la posizione non sono soggette alla limitazione a 1Hz
|
|
381
391
|
if (path === "navigation.position") {
|
|
382
|
-
return; // Esce subito
|
|
392
|
+
return; // Esce subito
|
|
383
393
|
}
|
|
384
394
|
|
|
385
395
|
// LIMITATORE DI FREQUENZA (RATE LIMITER) CLIENT-SIDE A 1HZ PER PERCORSO ATTIVO:
|
|
386
|
-
// Evita di eseguire calcoli trigonometrici, allocare oggetti in memoria dinamica
|
|
387
|
-
// e popolare i buffer smoothBuf/longBuf decine di volte al secondo per singolo sensore.
|
|
388
396
|
if (!lastPathProcessTimes[path]) lastPathProcessTimes[path] = 0;
|
|
389
397
|
if (now - lastPathProcessTimes[path] < 800) {
|
|
390
|
-
return; // Esce subito risparmiando cicli di calcolo
|
|
398
|
+
return; // Esce subito risparmiando cicli di calcolo
|
|
391
399
|
}
|
|
392
400
|
lastPathProcessTimes[path] = now;
|
|
393
401
|
|
|
@@ -805,65 +813,64 @@ function startDisplayLoop() {
|
|
|
805
813
|
}
|
|
806
814
|
|
|
807
815
|
// --- SLOW TIER (Salvataggio stato ogni 10 secondi) ---
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
816
|
+
if (lastAvgUIUpdate++ % 10 === 0) {
|
|
817
|
+
saveDashboardState();
|
|
818
|
+
}
|
|
811
819
|
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
820
|
+
// AGGIORNAMENTO FLUIDO MEDIE UI (Esecuzione a 1Hz costante ad ogni secondo)
|
|
821
|
+
const baseThreshold = CONFIG.averaging.stabilityThreshold || 0.95;
|
|
822
|
+
const breakout = CONFIG.averaging.stabilityBreakout || 15;
|
|
823
|
+
|
|
824
|
+
// CALCOLO DIFFERENZIALE: Tolleranza del vento proporzionale alla sensibilità di base
|
|
825
|
+
const windThreshold = Math.max(0.60, baseThreshold - 0.13);
|
|
818
826
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
}
|
|
835
|
-
safeSetText(ui.tackLabel, currentTackLabelMode);
|
|
827
|
+
let hObj = getCircularAverageFromBuffer(store.longBuf.hdg, CONFIG.averaging.longWindow * 2, false, now, baseThreshold, breakout);
|
|
828
|
+
let cObj = getCircularAverageFromBuffer(store.longBuf.cog, CONFIG.averaging.longWindow, false, now, baseThreshold, breakout);
|
|
829
|
+
|
|
830
|
+
// Applichiamo la soglia differenziale ottimizzata per i tre dati legati al vento
|
|
831
|
+
let awObj = getCircularAverageFromBuffer(store.longBuf.awa, CONFIG.averaging.longWindow, true, now, windThreshold, breakout);
|
|
832
|
+
let twObj = getCircularAverageFromBuffer(store.longBuf.twa, CONFIG.averaging.longWindow, true, now, windThreshold, breakout);
|
|
833
|
+
let twdObj = getCircularAverageFromBuffer(store.longBuf.twd, CONFIG.averaging.longWindow, false, now, windThreshold, breakout);
|
|
834
|
+
|
|
835
|
+
// --- GESTIONE DINAMICA ETICHETTA TACK/GYBE CON ISTERESI DI 10 GRADI ---
|
|
836
|
+
if (ui.tackLabel) {
|
|
837
|
+
const absTwa = Math.abs(radToDeg(store.raw["environment.wind.angleTrueWater"] || 0));
|
|
838
|
+
if (currentTackLabelMode === 'TACK' && absTwa > 95) {
|
|
839
|
+
currentTackLabelMode = 'GYBE';
|
|
840
|
+
} else if (currentTackLabelMode === 'GYBE' && absTwa < 85) {
|
|
841
|
+
currentTackLabelMode = 'TACK';
|
|
836
842
|
}
|
|
843
|
+
safeSetText(ui.tackLabel, currentTackLabelMode);
|
|
844
|
+
}
|
|
837
845
|
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
846
|
+
upUI(ui.hdg, hObj, store.raw["navigation.headingTrue"], true);
|
|
847
|
+
upUI(ui.cog, cObj, store.raw["navigation.courseOverGroundTrue"], true);
|
|
848
|
+
upUI(ui.awaAvg, awObj, store.raw["environment.wind.angleApparent"], false);
|
|
849
|
+
upUI(ui.twaAvg, twObj, store.raw["environment.wind.angleTrueWater"], false);
|
|
850
|
+
upUI(ui.twdAvg, twdObj, store.raw["environment.wind.directionTrue"], true);
|
|
851
|
+
|
|
852
|
+
if (hObj && twdObj) {
|
|
853
|
+
const reflectAngle = (targetRad, axisRad) => {
|
|
854
|
+
const dS = Math.sin(axisRad - targetRad);
|
|
855
|
+
const dC = Math.cos(axisRad - targetRad);
|
|
856
|
+
return Math.atan2(Math.sin(axisRad) * dC + Math.cos(axisRad) * dS, Math.cos(axisRad) * dC - Math.sin(axisRad) * dS);
|
|
857
|
+
};
|
|
858
|
+
const unstableH = !hObj.stable || !twdObj.stable || hObj.dev > CONFIG.averaging.stabilityBreakout;
|
|
859
|
+
if (!isNavigating) ui.tackHdg.innerHTML = "---°";
|
|
860
|
+
else if (unstableH) { ui.tackHdg.innerHTML = "---°"; ui.tackHdg.classList.add('unstable-data'); }
|
|
861
|
+
else {
|
|
862
|
+
const rH = (radToDeg(reflectAngle(hObj.val, twdObj.val)) + 360) % 360;
|
|
863
|
+
ui.tackHdg.innerHTML = `${Math.round(rH).toString().padStart(3, '0')}°`;
|
|
864
|
+
ui.tackHdg.classList.remove('unstable-data');
|
|
865
|
+
}
|
|
866
|
+
if (cObj) {
|
|
867
|
+
const unstableC = !cObj.stable || !twdObj.stable || cObj.dev > CONFIG.averaging.stabilityBreakout;
|
|
868
|
+
if (!isNavigating) ui.tackCog.innerHTML = "---°";
|
|
869
|
+
else if (unstableC) { ui.tackCog.innerHTML = "---°"; ui.tackCog.classList.add('unstable-data'); }
|
|
853
870
|
else {
|
|
854
|
-
const
|
|
855
|
-
ui.
|
|
856
|
-
ui.
|
|
857
|
-
}
|
|
858
|
-
if (cObj) {
|
|
859
|
-
const unstableC = !cObj.stable || !twdObj.stable || cObj.dev > CONFIG.averaging.stabilityBreakout;
|
|
860
|
-
if (!isNavigating) ui.tackCog.innerHTML = "---°";
|
|
861
|
-
else if (unstableC) { ui.tackCog.innerHTML = "---°"; ui.tackCog.classList.add('unstable-data'); }
|
|
862
|
-
else {
|
|
863
|
-
const rC = (radToDeg(reflectAngle(cObj.val, twdObj.val)) + 360) % 360;
|
|
864
|
-
ui.tackCog.innerHTML = `${Math.round(rC).toString().padStart(3, '0')}°`;
|
|
865
|
-
ui.tackCog.classList.remove('unstable-data');
|
|
866
|
-
}
|
|
871
|
+
const rC = (radToDeg(reflectAngle(cObj.val, twdObj.val)) + 360) % 360;
|
|
872
|
+
ui.tackCog.innerHTML = `${Math.round(rC).toString().padStart(3, '0')}°`;
|
|
873
|
+
ui.tackCog.classList.remove('unstable-data');
|
|
867
874
|
}
|
|
868
875
|
}
|
|
869
876
|
}
|