From b6c2a7e904e9c590c1aa0a3f371c5643d629a00b Mon Sep 17 00:00:00 2001 From: Giuseppe Raffa <77052701+sesee3@users.noreply.github.com> Date: Sat, 18 Apr 2026 12:32:32 +0200 Subject: [PATCH] Add initial KioskCore and API endpoint for data analysis - Created a new CSS file for kiosk styles, defining variables, typography, and layout for cards and toolbars. - Implemented new routes for data anlaysis page --- api/src/index.js | 3 + api/src/routes/sessions.js | 88 ++ api/src/storage/influx.js | 62 +- console/src/index.js | 5 + console/src/pages/kioskedit.html | 558 +++++++++++ console/src/pages/sessions.html | 922 ++++++++++++++++++ console/src/static/fonts/atkinson-bold.ttf | Bin 0 -> 54444 bytes console/src/static/fonts/atkinson-regular.ttf | Bin 0 -> 53504 bytes console/src/static/styles/kiosk.css | 634 ++++++++++++ realtime/src/routes/kiosk.js | 12 + realtime/src/store/db.js | 5 +- realtime/src/store/influx.js | 2 +- 12 files changed, 2287 insertions(+), 4 deletions(-) create mode 100644 api/src/routes/sessions.js create mode 100644 console/src/pages/kioskedit.html create mode 100644 console/src/pages/sessions.html create mode 100644 console/src/static/fonts/atkinson-bold.ttf create mode 100644 console/src/static/fonts/atkinson-regular.ttf create mode 100644 console/src/static/styles/kiosk.css create mode 100644 realtime/src/routes/kiosk.js diff --git a/api/src/index.js b/api/src/index.js index 28557a8..528cfc9 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -96,6 +96,9 @@ app.use('/params', paramsRoutes) const settingsRoutes = require('./routes/settings') app.use('/settings', settingsRoutes) +const sessionsRoutes = require('./routes/sessions') +app.use('/sessions', sessionsRoutes) + app.listen(PORT, '0.0.0.0', () => { console.log(`Started on port ${PORT}`); }); diff --git a/api/src/routes/sessions.js b/api/src/routes/sessions.js new file mode 100644 index 0000000..125e646 --- /dev/null +++ b/api/src/routes/sessions.js @@ -0,0 +1,88 @@ +const router = require('express').Router(); +const { query: dbQuery } = require('../storage/postgres'); +const { querySessionHistory, exportSessionCSV } = require('../storage/influx'); + +/** + * GET /sessions/history + * Lista tutte le sessioni di registrazione storiche da PostgreSQL (sessiondataref). + */ +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); + } catch (err) { + console.error('[sessions] history error:', err.message); + res.status(500).json({ error: 'internal server error' }); + } +}); + +/** + * GET /sessions/:sensorId/data?session=sXXXX&from=ISO&to=ISO + * Restituisce i dati storici di una sessione come JSON (righe pivotate da InfluxDB). + */ +router.get('/:sensorId/data', async (req, res) => { + const { sensorId } = req.params; + const { session, from, to } = req.query; + + if (!session) return res.status(400).json({ error: 'session param required' }); + + try { + let since = from || null; + if (!since) { + const result = await dbQuery( + `SELECT created_at FROM sessiondataref WHERE session_id = $1`, + [session], + 'sensors' + ); + since = result.rows[0]?.created_at?.toISOString() || '-30d'; + } + + const until = to ? new Date(parseInt(to)).toISOString() : null; + const rows = await querySessionHistory(sensorId, session, since, until); + res.json(rows); + } catch (err) { + console.error('[sessions] data error:', err.message); + res.status(500).json({ error: 'internal server error' }); + } +}); + +/** + * GET /sessions/:sensorId/csv?session=sXXXX&from=ms&to=ms + * Esporta i dati di una sessione come CSV (supporta intervallo opzionale). + */ +router.get('/:sensorId/csv', async (req, res) => { + const { sensorId } = req.params; + const { session, from, to } = req.query; + + if (!session) return res.status(400).json({ error: 'session param required' }); + + try { + let since = from ? new Date(parseInt(from)).toISOString() : null; + if (!since) { + const result = await dbQuery( + `SELECT created_at FROM sessiondataref WHERE session_id = $1`, + [session], + 'sensors' + ); + since = result.rows[0]?.created_at?.toISOString() || '-30d'; + } + + const until = to ? new Date(parseInt(to)).toISOString() : null; + const csv = await exportSessionCSV(sensorId, session, since, until); + + if (!csv) return res.status(404).json({ error: 'No data found for this session' }); + + res.setHeader('Content-Type', 'text/csv'); + res.setHeader('Content-Disposition', `attachment; filename="session_${session}_${sensorId}.csv"`); + res.send(csv); + } catch (err) { + console.error('[sessions] csv error:', err.message); + res.status(500).json({ error: 'CSV export failed' }); + } +}); + +module.exports = router; diff --git a/api/src/storage/influx.js b/api/src/storage/influx.js index c369917..0944bdd 100644 --- a/api/src/storage/influx.js +++ b/api/src/storage/influx.js @@ -60,6 +60,64 @@ async function query(bucket, relativeTime, measurement, sensor, field) { } +const sessionBucket = process.env.INFLX_BUCKET || 'logs'; + +/** + * Query storica per una sessione di registrazione. + * @param {string} sensor - nome sensore + * @param {string} session - session_id (tag InfluxDB) + * @param {string} since - ISO timestamp o duration (es. "-30d") + * @param {string|null} until - ISO timestamp fine (opzionale) + * @returns {Promise>} + */ +async function querySessionHistory(sensor, session, since, until = null) { + const rangeStr = until ? `start: ${since}, stop: ${until}` : `start: ${since}`; + const fluxQuery = ` + from(bucket: "${sessionBucket}") + |> range(${rangeStr}) + |> filter(fn: (r) => r._measurement == "logs") + |> filter(fn: (r) => r.sensor == "${sensor}") + |> filter(fn: (r) => r.session == "${session}") + |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value") + |> sort(columns: ["_time"]) + `; + const rows = []; + return new Promise((resolve, reject) => { + querying.queryRows(fluxQuery, { + next(row, tableMeta) { rows.push(tableMeta.toObject(row)); }, + error: reject, + complete() { resolve(rows); }, + }); + }); +} + +/** + * Esporta i dati di una sessione come stringa CSV. + * @param {string} sensor + * @param {string} session + * @param {string} since + * @param {string|null} until + * @returns {Promise} + */ +async function exportSessionCSV(sensor, session, since, until = null) { + const rows = await querySessionHistory(sensor, session, since, until); + if (rows.length === 0) return ''; + const metaKeys = new Set(['result', 'table', '_start', '_stop', '_measurement', 'sensor', 'session', '']); + const fieldNames = new Set(); + for (const row of rows) { + for (const key of Object.keys(row)) { + if (!metaKeys.has(key) && key !== '_time') fieldNames.add(key); + } + } + const fields = Array.from(fieldNames).sort(); + const header = ['timestamp', ...fields].join(','); + const csvRows = rows.map(row => { + const values = fields.map(f => { const v = row[f]; return (v == null) ? '' : v; }); + return [row._time || '', ...values].join(','); + }); + return header + '\n' + csvRows.join('\n') + '\n'; +} + async function checkInflux() { try { const result = await querying.collectRows( @@ -78,9 +136,11 @@ async function checkInflux() { } module.exports = { - write:append, + write: append, writeBatch, query, + querySessionHistory, + exportSessionCSV, checkInflux } diff --git a/console/src/index.js b/console/src/index.js index b112a4e..1358213 100644 --- a/console/src/index.js +++ b/console/src/index.js @@ -91,6 +91,11 @@ app.get('/rulesets', renderPage('rulesets', { apiUrl: process.env.API_URL || 'http://localhost:3003' })); +app.get('/sessions', renderPage('sessions', { + apiUrl: process.env.API_URL || 'http://localhost:3003', + mapboxToken: process.env.MAPBOX_TOKEN || '' +})); + app.listen(PORT, '0.0.0.0', () => { console.log(`Started on port ${PORT}`); }); diff --git a/console/src/pages/kioskedit.html b/console/src/pages/kioskedit.html new file mode 100644 index 0000000..f362d13 --- /dev/null +++ b/console/src/pages/kioskedit.html @@ -0,0 +1,558 @@ + + + + + + Kiosk Dashboard + + + + + + + + +
+
Trascina o aggiungi una card per iniziare
+
+ + +
+
1u = 0px
+
+ + + + +
+

0 cards

+ + + + + + + + + +
+ + + + + + + + diff --git a/console/src/pages/sessions.html b/console/src/pages/sessions.html new file mode 100644 index 0000000..7265e1e --- /dev/null +++ b/console/src/pages/sessions.html @@ -0,0 +1,922 @@ + + + + + + + + + + +
+ + +
+
+
Caricamento dati sessione...
+
+ + +
+
+ + +
+
Caricamento sessioni...
+
+
+
+ + +
+
+ +

Sessioni

+
+
+ + +
+
+ + +
+ + +
+
+
Nessun dato GPS per questa sessione
+ +
+ + +
+
+
+ + +
+
+ + + + +
+
+
+
+
+ + +
+
+

Dettaglio

+ +
+
+ +
+
+ + +
+
+ +
+
+
+
+
+
+
+
+ + + +
+
+ +
+
+ +
+ +
+ + + + diff --git a/console/src/static/fonts/atkinson-bold.ttf b/console/src/static/fonts/atkinson-bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..80da7d0a9a99f8857df5b251dc775f9d6e0fc4ad GIT binary patch literal 54444 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 Q;0c60B+oe{kMNxTU+8d%v;Y7A literal 0 HcmV?d00001 diff --git a/console/src/static/fonts/atkinson-regular.ttf b/console/src/static/fonts/atkinson-regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..f0edd19047f7272b1abac2169850cb28bec503cd GIT binary patch literal 53504 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 { + const { session_id, sensor_code, value, timestamp } = req.body; + if (!session_id || !sensor_code || value === undefined) { + return res.status(400).json({ error: 'Missing required fields' }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/realtime/src/store/db.js b/realtime/src/store/db.js index d5f28f5..2595b80 100644 --- a/realtime/src/store/db.js +++ b/realtime/src/store/db.js @@ -11,8 +11,9 @@ const baseConfig = { }; const dbs = { - data: { name: process.env.DATA_DB || 'data' }, - sensors: { name: process.env.SENSORS_DB || 'sensors' } + data: { name: 'data' }, + sensors: { name: 'sensors' }, + kiosk: { name: 'kiosk' }, } const pools = {}; diff --git a/realtime/src/store/influx.js b/realtime/src/store/influx.js index 63bbfc2..dc1b56b 100644 --- a/realtime/src/store/influx.js +++ b/realtime/src/store/influx.js @@ -5,7 +5,7 @@ const client = new InfluxDB({ token: process.env.INFLX_TOKEN, }); -const bucket = process.env.INFLX_BUCKET || 'sensors'; +const bucket = process.env.INFLX_BUCKET || 'logs'; const org = process.env.INFLX_ORG; const writeApi = client.getWriteApi(org, bucket, 'ms', {