Files
signalk-plugin/plugin/config/skFlow.js
Giuseppe Raffa bb8d267cd4 Aggiunta stili CSS per Kiosk, struttura HTML per la Mappa e Riferimenti ai Sensori
• Creato un nuovo file CSS per gli stili del chiosco (kiosk) con variabili, stili per le schede (card) e animazioni.
• Aggiunto un file HTML per l'interfaccia della mappa utilizzando Mapbox, inclusi gli stili e il JavaScript per le funzionalità della mappa.
• Introdotto un file JSON per i riferimenti ai sensori, definendo percorsi ed elementi per i dati di temperatura, vento, onde, posizione, batteria, motore e sistema.

Co-authored-by: Copilot <copilot@github.com>
2026-04-23 16:19:11 +02:00

172 lines
5.3 KiB
JavaScript

let skApp = null;
/**
* Inizializza il modulo con l'istanza dell'app Signal K.
* Da chiamare una sola volta nel plugin.start()
* @param {Object} app - l'istanza dell'applicazione Signal K
*/
function init(app) {
skApp = app;
}
/**
* Pubblica un set di dati nel data browser di Signal K tramite i delta.
* @param {Object} data - Oggetto JSON dove le chiavi sono i percorsi e i valori sono i dati da pubblicare
*/
function publish(data) {
//TODO: Controlla se serve aggiungere typeof skApp.handleMessage !== 'function' (controlla che esista la funzione handleMessage, ma in teoria esiste sempre)
if (!skApp) {
console.error('[SKFLOW] skApp non inizializzato')
return;
}
if (!data || typeof data !== 'object') {
console.error('[SKFLOW] Dati non validi')
return;
}
const values = Object.entries(data).map(([path, value]) => {
return {
path: path,
value: value
};
});
//La funzione non continua se non ci sono dati
//TODO: Controllare se serve davvero, non dovrebbe interrompersi già al check di data?
if (values.length === 0) return;
// Viene creato un "Delta Update" con l'ID del plugin 'meb.plugin' e l'array di valori.
skApp.handleMessage('meb.plugin', {
updates: [
{
values: values
}
]
});
}
/**
* Ottieni i dati dal Data-Browser di Signal K
* @param {String} path - Il path Signal K
* @returns {*} Il dato
*/
function get(path) {
if (!skApp) {
return null;
}
const valObj = skApp.getSelfPath(path);
return valObj ? valObj.value : null;
}
/**
* Ottieni tutti i dati nel databrowser di Signal K che corrispondono ad un ID o ad una sorgente specifica.
* @param {String} source - Il parametro da confrontare con il sorgente ($source o source) o ID del dato.
* @returns {Object} Un oggetto contenente path e valori trovati.
*/
function getBySource(source) {
if (!skApp) return {};
const results = {};
const self = skApp.signalk?.self || skApp.signalk?.retrieve()?.vessels?.[skApp.selfId] || {};
if (!self || Object.keys(self).length === 0) {
console.log('[SKFLOW] Nessun dato trovato nel databrowser');
return results;
}
const traverse = (obj, path = '') => {
if (!obj || typeof obj !== 'object') return;
// Se l'oggetto ha una proprietà 'value', verifichiamo la sorgente
if (Object.prototype.hasOwnProperty.call(obj, 'value')) {
const hasSource = obj.$source === source || obj.source === source || obj.id === source;
if (hasSource) {
results[path] = obj.value;
}
}
// Esplora i sotto-oggetti escludendo chiavi di sistema che non sono percorsi SK
const skip = ['value', 'timestamp', '$source', 'source', 'meta', 'sentence', 'talker'];
for (const key in obj) {
if (skip.includes(key)) continue;
const subPath = path ? `${path}.${key}` : key;
traverse(obj[key], subPath);
}
};
traverse(self);
return results;
}
/**
* Ottieni tutti i dati nel databrowser di Signal K il cui path inizia con la stringa specificata.
* @param {String} filterPath - La stringa con cui deve iniziare il path (es. "custom.plugin").
* @returns {Object} Un oggetto contenente path e valori trovati.
*/
function getWithFilter(filterPath) {
if (!skApp) return {};
const results = {};
const self = skApp.signalk?.self || skApp.signalk?.retrieve()?.vessels?.[skApp.selfId] || {};
if (!self || Object.keys(self).length === 0) {
return results;
}
const traverse = (obj, path = '') => {
if (!obj || typeof obj !== 'object') return;
// Se l'oggetto ha una proprietà 'value', verifichiamo se il path corrisponde al filtro
if (Object.prototype.hasOwnProperty.call(obj, 'value')) {
if (path.startsWith(filterPath)) {
results[path] = obj.value;
}
}
// Esplora i sotto-oggetti escludendo chiavi di sistema
const skip = ['value', 'timestamp', '$source', 'source', 'meta', 'sentence', 'talker'];
for (const key in obj) {
if (skip.includes(key)) continue;
const subPath = path ? `${path}.${key}` : key;
// Ottimizzazione: se `subPath` non inizia con `filterPath` E `filterPath` non inizia con `subPath`,
// possiamo evitare di scendere in rami completamente irrilevanti.
// (es. filter = "environment." e subPath = "navigation." -> skippa)
if (!subPath.startsWith(filterPath) && !filterPath.startsWith(subPath)) continue;
traverse(obj[key], subPath);
}
};
traverse(self);
return results;
}
/**
* Ottieni un oggetto con path e valori per una lista specifica di path.
* @param {Array<String>} data - Un array contenente i path di Signal K da recuperare.
* @returns {Object} Un oggetto JSON con elementi path: value.
*/
function getFrom(data) {
if (!Array.isArray(data)) return {};
const results = {};
for (const path of data) {
results[path] = get(path);
}
return results;
}
module.exports = {
init,
publish,
get,
getBySource,
getWithFilter,
getFrom
};