Files
signalk-plugin/plugin/tools/logRecorder.js
2026-01-06 17:36:58 +01:00

220 lines
6.1 KiB
JavaScript

/**
* logRecorder.js - Gestione registrazione dati separata
* Centralizza tutte le funzioni di logging del dataset
*/
const path = require('path');
const { datasetInit, appendData } = require('../datasetModels/datasetCore');
let app = null;
let recordingInterval = null;
let isRecording = false;
// Stato condiviso della registrazione
const recordingState = {
active: false,
startTime: null,
entryCount: 0,
currentFile: null,
stream: null
};
/**
* Inizializza il recorder con l'istanza di SignalK app
*/
function init(signalkApp) {
app = signalkApp;
console.log('[LogRecorder] Inizializzato');
}
/**
* Raccoglie i dati dai sensori SignalK
*/
function collectSensorData() {
const getSK = (p) => {
const v = app.getSelfPath(p);
return v && v.value !== undefined && v.value !== null ? v.value : null;
};
return {
timestamp: new Date().toISOString(),
// Posizione
latitude: getSK('navigation.position')?.latitude ?? null,
longitude: getSK('navigation.position')?.longitude ?? null,
speed: getSK('navigation.speedOverGround'),
heading: getSK('navigation.headingTrue'),
// Batteria Trazione
traction_voltage: getSK('electrical.batteries.traction.Voltage'),
traction_current: getSK('electrical.batteries.traction.current'),
traction_soc: getSK('electrical.batteries.traction.stateOfCharge'),
traction_temperature: getSK('electrical.batteries.traction.temperature'),
traction_power: getSK('electrical.batteries.traction.power'),
// Batteria Servizio
service_voltage: getSK('electrical.batteries.service.Voltage'),
service_current: getSK('electrical.batteries.service.current'),
service_soc: getSK('electrical.batteries.service.stateOfCharge'),
service_temperature: getSK('electrical.batteries.service.temperature'),
// Meteo (da OpenMeteo condiviso)
temperature: getSK('meb.temperature'),
windSpeed: getSK('meb.appleWindSpeed'),
windDirection: getSK('meb.appleWindDirection'),
// Onde
waveHeight: getSK('meb.waves.waveHeight'),
wavePeriod: getSK('meb.waves.wavePeriod'),
waveDirection: getSK('meb.waves.waveDirection')
};
}
/**
* Crea un nuovo file di log
*/
function createNewLogFile() {
const headers = [
'timestamp',
'latitude', 'longitude', 'speed', 'heading',
'traction_voltage', 'traction_current', 'traction_soc', 'traction_temperature', 'traction_power',
'service_voltage', 'service_current', 'service_soc', 'service_temperature',
'temperature', 'windSpeed', 'windDirection',
'waveHeight', 'wavePeriod', 'waveDirection'
];
const result = datasetInit(headers);
if (result) {
recordingState.currentFile = result.fileName;
recordingState.stream = result.stream;
console.log(`[LogRecorder] Nuovo file: ${result.fileName}`);
}
return result;
}
/**
* Scrive una riga di dati nel log
*/
function writeLogEntry(data) {
if (!recordingState.stream) return false;
const values = [
data.timestamp,
data.latitude, data.longitude, data.speed, data.heading,
data.traction_voltage, data.traction_current, data.traction_soc, data.traction_temperature, data.traction_power,
data.service_voltage, data.service_current, data.service_soc, data.service_temperature,
data.temperature, data.windSpeed, data.windDirection,
data.waveHeight, data.wavePeriod, data.waveDirection
];
appendData(values);
recordingState.entryCount++;
return true;
}
/**
* Avvia la registrazione
* @param {number} intervalMs - Intervallo in millisecondi (default 2000)
*/
function startRecording(intervalMs = 2000) {
if (isRecording) {
console.log('[LogRecorder] Registrazione già attiva');
return false;
}
if (!app) {
console.error('[LogRecorder] App non inizializzata');
return false;
}
const fileResult = createNewLogFile();
if (!fileResult) {
console.error('[LogRecorder] Impossibile creare file di log');
return false;
}
recordingState.active = true;
recordingState.startTime = Date.now();
recordingState.entryCount = 0;
isRecording = true;
recordingInterval = setInterval(() => {
const data = collectSensorData();
writeLogEntry(data);
}, intervalMs);
console.log(`[LogRecorder] Registrazione avviata (ogni ${intervalMs}ms)`);
return true;
}
/**
* Ferma la registrazione
*/
function stopRecording() {
if (!isRecording) {
console.log('[LogRecorder] Nessuna registrazione attiva');
return false;
}
if (recordingInterval) {
clearInterval(recordingInterval);
recordingInterval = null;
}
if (recordingState.stream) {
recordingState.stream.end();
}
const duration = Date.now() - recordingState.startTime;
console.log(`[LogRecorder] Registrazione fermata. Durata: ${Math.round(duration / 1000)}s, Entries: ${recordingState.entryCount}`);
recordingState.active = false;
recordingState.stream = null;
isRecording = false;
return {
duration,
entries: recordingState.entryCount,
file: recordingState.currentFile
};
}
/**
* Riavvia la registrazione (nuovo file)
*/
function restartRecording(intervalMs = 2000) {
stopRecording();
return startRecording(intervalMs);
}
/**
* Ottiene lo stato corrente della registrazione
*/
function getStatus() {
return {
isRecording,
active: recordingState.active,
startTime: recordingState.startTime,
entryCount: recordingState.entryCount,
currentFile: recordingState.currentFile,
runningTime: isRecording ? Date.now() - recordingState.startTime : 0
};
}
/**
* Verifica se la registrazione è attiva
*/
function isActive() {
return isRecording;
}
module.exports = {
init,
startRecording,
stopRecording,
restartRecording,
getStatus,
isActive,
collectSensorData
};