feat+fix: changed the primary data source for the data analysis and added the relative card in the dashboard page.

This commit is contained in:
Giuseppe Raffa
2026-04-18 12:43:50 +02:00
parent b6c2a7e904
commit ba0dbe6baf
4 changed files with 89 additions and 16 deletions

View File

@@ -1,19 +1,39 @@
const router = require('express').Router();
const { query: dbQuery } = require('../storage/postgres');
const { querySessionHistory, exportSessionCSV } = require('../storage/influx');
const { listInfluxSessions, querySessionHistory, exportSessionCSV } = require('../storage/influx');
/**
* GET /sessions/history
* Lista tutte le sessioni di registrazione storiche da PostgreSQL (sessiondataref).
* Fonte primaria: InfluxDB (tag sensor + session sul measurement "logs").
* Arricchisce con i metadati opzionali da PostgreSQL (sessiondataref): nome, tags, descrizione.
*/
router.get('/history', async (req, res) => {
try {
const result = await dbQuery(
`SELECT * FROM sessiondataref ORDER BY created_at DESC LIMIT 100`,
[],
'sensors'
);
res.json(result.rows);
const sessions = await listInfluxSessions();
// Arricchisci con dati PostgreSQL (opzionale — può fallire senza bloccare)
let pgMap = {};
try {
const result = await dbQuery(
`SELECT * FROM sessiondataref`,
[],
'sensors'
);
result.rows.forEach(r => { pgMap[r.session_id] = r; });
} catch (_) {}
const enriched = sessions.map(s => ({
session_id: s.session,
sensor_name: s.sensor,
startTime: s.startTime,
endTime: s.endTime,
// campi opzionali da PostgreSQL
name: pgMap[s.session]?.name || null,
description: pgMap[s.session]?.description || null,
tags: pgMap[s.session]?.tags || [],
}));
res.json(enriched);
} catch (err) {
console.error('[sessions] history error:', err.message);
res.status(500).json({ error: 'internal server error' });

View File

@@ -118,6 +118,51 @@ async function exportSessionCSV(sensor, session, since, until = null) {
return header + '\n' + csvRows.join('\n') + '\n';
}
/**
* Utility interna: esegue una Flux query e restituisce le righe come array di oggetti.
*/
function runFlux(fluxQuery) {
const rows = [];
return new Promise((resolve, reject) => {
querying.queryRows(fluxQuery, {
next(row, tableMeta) { rows.push(tableMeta.toObject(row)); },
error: reject,
complete() { resolve(rows); },
});
});
}
/**
* Elenca tutte le sessioni presenti in InfluxDB, con primo e ultimo timestamp.
* Sorgente di verità: tag sensor + session sul measurement "logs".
* @param {string} [lookback='-5y'] - range di ricerca (es. '-365d', '-5y')
* @returns {Promise<Array<{session, sensor, startTime, endTime}>>}
*/
async function listInfluxSessions(lookback = '-5y') {
const base = `
from(bucket: "${sessionBucket}")
|> range(start: ${lookback})
|> filter(fn: (r) => r._measurement == "logs")
|> group(columns: ["sensor", "session"])
|> keep(columns: ["_time", "sensor", "session"])
`;
const [firstRows, lastRows] = await Promise.all([
runFlux(base + '|> first()'),
runFlux(base + '|> last()'),
]);
const map = {};
firstRows.forEach(r => {
if (!r.session) return;
map[r.session] = { session: r.session, sensor: r.sensor, startTime: r._time };
});
lastRows.forEach(r => {
if (map[r.session]) map[r.session].endTime = r._time;
});
return Object.values(map).sort((a, b) => new Date(b.startTime) - new Date(a.startTime));
}
async function checkInflux() {
try {
const result = await querying.collectRows(
@@ -139,6 +184,7 @@ module.exports = {
write: append,
writeBatch,
query,
listInfluxSessions,
querySessionHistory,
exportSessionCSV,
checkInflux