feat: update session handling and add session history endpoint

This commit is contained in:
Giuseppe Raffa
2026-04-16 15:37:10 +02:00
parent 5912c00a82
commit 981f498eb7
5 changed files with 354 additions and 92 deletions

View File

@@ -258,31 +258,46 @@ function getColorForField(key) {
}
const FIELD_DEFS = {
temp: { name: 'Temperatura', unit: '°C', category: 'weather' },
hum: { name: 'Umidita', unit: '%', category: 'weather' },
pres: { name: 'Pressione', unit: 'hPa', category: 'weather' },
wSpd: { name: 'Velocita Vento', unit: 'km/h', category: 'weather' },
wDir: { name: 'Direzione Vento', unit: '°', category: 'weather' },
gust: { name: 'Raffiche', unit: 'km/h', category: 'weather' },
rain: { name: 'Pioggia', unit: 'mm', category: 'weather' },
prec: { name: 'Precipitazioni', unit: 'mm', category: 'weather' },
lat: { name: 'Latitudine', unit: '°', category: 'navigation' },
lon: { name: 'Longitudine', unit: '°', category: 'navigation' },
hdg: { name: 'Heading', unit: '°', category: 'navigation' },
sog: { name: 'Velocita SOG', unit: 'kn', category: 'navigation' },
cog: { name: 'Rotta COG', unit: '°', category: 'navigation' },
depth: { name: 'Profondita', unit: 'm', category: 'navigation' },
engTemp: { name: 'Temp. Motore', unit: '°C', category: 'engine' },
wvH: { name: 'Altezza Onde', unit: 'm', category: 'weather' },
wvP: { name: 'Periodo Onde', unit: 's', category: 'weather' },
wvD: { name: 'Direzione Onde', unit: '°', category: 'weather' },
curD: { name: 'Dir. Corrente', unit: '°', category: 'weather' },
curV: { name: 'Vel. Corrente', unit: 'm/s', category: 'weather' },
fTemp: { name: 'Prev. Temperatura', unit: C', category: 'weather' },
fWSpd: { name: 'Prev. Vento', unit: 'km/h', category: 'weather' }
// Meteo (da openmeteo → SignalK → logs)
'meb.forecasts.temperature': { name: 'Temperatura', unit: '°C', category: 'weather' },
'meb.forecast.wind.speed': { name: 'Velocita Vento', unit: 'km/h', category: 'weather' },
'meb.forecast.wind.direction': { name: 'Direzione Vento', unit: '°', category: 'weather' },
'meb.forecast.wind.gusts': { name: 'Raffiche', unit: 'km/h', category: 'weather' },
'meb.forecast.humidity': { name: 'Umidita', unit: '%', category: 'weather' },
'meb.forecast.pressure': { name: 'Pressione', unit: 'hPa', category: 'weather' },
'meb.forecast.precipitation': { name: 'Precipitazioni', unit: 'mm', category: 'weather' },
'meb.forecast.rain': { name: 'Pioggia', unit: 'mm', category: 'weather' },
'meb.forecast.cloudCover': { name: 'Copertura Nuvole', unit: '%', category: 'weather' },
'meb.forecast.precipitationProbability': { name: 'Prob. Precipitazioni', unit: '%', category: 'weather' },
// Marine
'meb.waves.height': { name: 'Altezza Onde', unit: 'm', category: 'weather' },
'meb.waves.direction': { name: 'Direzione Onde', unit: '°', category: 'weather' },
'meb.waves.period': { name: 'Periodo Onde', unit: 's', category: 'weather' },
'meb.waves.peakPeriod': { name: 'Periodo Picco', unit: 's', category: 'weather' },
'meb.waves.currentVelocity': { name: 'Vel. Corrente', unit: 'm/s', category: 'weather' },
'meb.waves.currentDirection': { name: 'Dir. Corrente', unit: '°', category: 'weather' },
// Navigazione
'navigation.position.latitude': { name: 'Latitudine', unit: '°', category: 'navigation' },
'navigation.position.longitude': { name: 'Longitudine', unit: '°', category: 'navigation' },
'navigation.headingTrue': { name: 'Heading', unit: '°', category: 'navigation' },
'navigation.speedOverGround': { name: 'Velocita SOG', unit: 'kn', category: 'navigation' },
'navigation.courseOverGroundTrue': { name: 'Rotta COG', unit: '°', category: 'navigation' },
// Elettrica
'electrical.batteries.service.Voltage': { name: 'Batteria Serv. V', unit: 'V', category: 'engine' },
'electrical.batteries.service.current': { name: 'Batteria Serv. A', unit: 'A', category: 'engine' },
'electrical.batteries.service.stateOfCharge': { name: 'Batteria Serv. SoC', unit: '%', category: 'engine' },
'electrical.batteries.traction.Voltage': { name: 'Batteria Traz. V', unit: 'V', category: 'engine' },
'electrical.batteries.traction.current': { name: 'Batteria Traz. A', unit: 'A', category: 'engine' },
'electrical.batteries.traction.stateOfCharge': { name: 'Batteria Traz. SoC', unit: '%', category: 'engine' },
'electrical.batteries.traction.temperature': { name: 'Batteria Traz. Temp', unit: '°C', category: 'engine' },
'electrical.batteries.traction.power': { name: 'Batteria Traz. W', unit: 'W', category: 'engine' },
// Motore
'propulsion.0.revolutions': { name: 'Giri Motore', unit: 'RPM', category: 'engine' },
// Sistema
'system.uptime': { name: 'Uptime', unit: 's', category: 'engine' }
};
const MEASUREMENT_CATEGORY = { weather: 'weather', navigation: 'navigation', engine: 'engine' };
const ALWAYS_FILL_BOTTOM_FIELDS = ['lat', 'lon'];
const MEASUREMENT_CATEGORY = { weather: 'weather', navigation: 'navigation', logs: 'navigation', engine: 'engine' };
const ALWAYS_FILL_BOTTOM_FIELDS = ['navigation.position.latitude', 'navigation.position.longitude'];
async function loadSessions() {
document.getElementById('sessionList').innerHTML = '<div class="session-loading">Caricamento...</div>';
@@ -301,23 +316,27 @@ async function loadSessions() {
const meta = typeof rawMeta === 'string' ? JSON.parse(rawMeta) : rawMeta;
const item = document.createElement('div');
item.className = 'session-item';
const connTime = meta.connectedAt ? new Date(meta.connectedAt * 1000).toLocaleTimeString('it-IT') : '—';
item.innerHTML = `<div class="session-item-info"><strong>${meta.name || sId}</strong><span class="session-item-id">${sId}</span></div><div class="session-item-meta"><span class="session-item-time">Connesso: ${connTime}</span><div class="session-item-dot"></div></div>`;
const connTime = meta.connectedAt ? new Date(meta.connectedAt).toLocaleTimeString('it-IT') : '—';
const sessId = meta.session || '—';
item.innerHTML = `<div class="session-item-info"><strong>${meta.name || sId}</strong><span class="session-item-id">${sessId}</span></div><div class="session-item-meta"><span class="session-item-time">Connesso: ${connTime}</span><div class="session-item-dot"></div></div>`;
item.onclick = () => selectSession(sId, meta);
document.getElementById('sessionList').appendChild(item);
}
} catch (err) { }
}
let currentSessionId = null; // InfluxDB session tag (es. s1234)
function selectSession(sId, meta) {
currentSensorId = sId;
sessionStartTime = meta.connectedAt ? meta.connectedAt * 1000 : Date.now();
currentSessionId = meta.session || null;
sessionStartTime = meta.connectedAt ? new Date(meta.connectedAt).getTime() : Date.now();
document.getElementById('sessionOverlay').style.display = 'none';
document.getElementById('mainContent').style.display = '';
document.getElementById('bottomBar').style.display = '';
document.getElementById('sensorName').textContent = meta.name || sId;
document.getElementById('sessionInfoTitle').textContent = `Sensore: ${meta.name || sId}`;
document.getElementById('currentSessionLabel').textContent = meta.sessionLabel || meta.session || sId;
document.getElementById('currentSessionLabel').textContent = currentSessionId || sId;
liveData = {};
Object.values(miniCharts).forEach(c => c.destroy());
miniCharts = {};
@@ -389,7 +408,11 @@ function handleSensorData(msg) {
if (redrawExpChart) updateExpandedChart();
if (redrawCompChart) updateCompChart();
if (measurement === 'logs' && fields.lat && fields.lon) updateMap(fields.lat, fields.lon, fields.hdg, fields.wDir, fields.wvD);
const lat = fields['navigation.position.latitude'];
const lon = fields['navigation.position.longitude'];
if (lat != null && lon != null) {
updateMap(lat, lon, fields['navigation.headingTrue'], fields['meb.forecast.wind.direction'], fields['meb.waves.direction']);
}
}
function createHybCard(key, def, val) {
@@ -681,7 +704,8 @@ document.getElementById('downloadBtn').onclick = async () => {
btn.textContent = '...';
await fetch(`${REALTIME_URL}/sessions/${currentSensorId}/flush`, { method: 'POST' });
const csvUrl = `${REALTIME_URL}/sessions/${currentSensorId}/csv?from=${sessionStartTime}`;
const sessionParam = currentSessionId ? `&session=${currentSessionId}` : '';
const csvUrl = `${REALTIME_URL}/sessions/${currentSensorId}/csv?from=${sessionStartTime}${sessionParam}`;
const res = await fetch(csvUrl);
const blob = await res.blob();
@@ -733,12 +757,12 @@ document.getElementById('cancelSessionLabelBtn').onclick = () => {
};
document.getElementById('saveSessionLabelBtn').onclick = async () => {
const label = document.getElementById('sessionLabelInput').value.trim();
if (!label || !currentSensorId) return;
if (!label || !currentSensorId || !currentSessionId) return;
try {
const res = await fetch(`${REALTIME_URL}/sessions/${currentSensorId}/label`, {
method: 'POST',
const res = await fetch(`${REALTIME_URL}/sessions/${currentSensorId}/details`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ label })
body: JSON.stringify({ session: currentSessionId, name: label })
});
if (res.ok) {
document.getElementById('currentSessionLabel').textContent = label;