feat: Implement rulesets and layout management for kiosk plugin

- Added rulesets manager to handle various data types and updates via HTTP and WebSocket.
- Introduced layout store for managing kiosk layouts with caching and server synchronization.
- Enhanced dashboard and data routes to support new layout and ruleset features.
- Updated kiosk HTML and JavaScript to utilize new layout rendering and data binding.
- Removed obsolete map route and integrated map functionality into the new tile renderer.
- Improved Telegram commands to reflect changes in data structure and logging.
- Refactored weather fetching intervals to prevent multiple instances.
- Added SSE stream for real-time layout updates in the kiosk.
This commit is contained in:
Giuseppe Raffa
2026-05-12 10:17:54 +02:00
parent bb8d267cd4
commit c2c1598226
27 changed files with 1061 additions and 326 deletions

View File

@@ -10,7 +10,4 @@ router.get('/', (req, res) => {
res.sendFile(path.join(kioskPath, 'dashboard.html'));
});
router.get('/api/', (req, res) => {});
module.exports = router;

View File

@@ -4,21 +4,23 @@ const db = require('../../config/skFlow')
const config = require('../../config/configManager.js')
router.get('/', (req, res) => {
const { path } = req.query;
const data = db.get(path);
res.json(data);
const { path, source } = req.query;
if (source) {
return res.json(db.getBySource(source));
}
res.json(db.get(path));
});
router.get('/', (req, res) => {
const { source } = req.query;
const data = db.getBySource(source);
res.json(data);
});
const maskToken = (t) => {
if (!t) return null;
const s = String(t);
return s.length > 8 ? `${s.slice(0, 5)}${s.slice(-3)}` : '***';
};
router.get('/info', (req, res) => {
const info = {
telegram: config.getTelegramToken(),
telegram_configured: Boolean(config.getTelegramToken()),
telegram_token_preview: maskToken(config.getTelegramToken()),
sensor: {
name: config.getSensorName(),

View File

@@ -3,16 +3,48 @@ const express = require('express');
const path = require('path');
const fs = require('fs');
const configManager = require('../../config/configManager.js');
const layoutStore = require('../../tools/kiosk/server-layout-store.js');
const kioskPath = path.join(__dirname, '../../tools/kiosk');
const htmlFile = path.join(kioskPath, 'kiosk.html');
// API: layout corrente
router.get('/layout', (req, res) => {
const l = layoutStore.get();
if (!l) return res.status(404).json({ error: 'no layout' });
res.json(l);
});
// SSE stream per gli update del layout (live, niente polling)
router.get('/stream', (req, res) => {
res.set({
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'X-Accel-Buffering': 'no',
});
res.flushHeaders?.();
// invia subito il layout corrente
const cur = layoutStore.get();
if (cur) res.write(`event: layout\ndata: ${JSON.stringify(cur)}\n\n`);
const off = layoutStore.onUpdate((layout) => {
try { res.write(`event: layout\ndata: ${JSON.stringify(layout)}\n\n`); } catch {}
});
const ping = setInterval(() => { try { res.write(': ping\n\n'); } catch {} }, 25000);
req.on('close', () => { clearInterval(ping); off(); });
});
router.use('/', express.static(kioskPath));
router.get('/', (req, res) => {
const apiUrl = process.env.API_URL || 'https://api.mebboat.it';
const realtimeUrl = process.env.REALTIME_URL || 'https://realtime.mebboat.it';
const realtimeWsUrl = process.env.REALTIME_SOCKET_URL || 'wss://realtime.mebboat.it';
const mapboxKey = process.env.MAPBOX_API_KEY || '';
const sensorCode = configManager.getSensorCode();
const sensorName = configManager.getSensorName();
@@ -21,6 +53,7 @@ router.get('/', (req, res) => {
<meta name="api-url" content="${esc(apiUrl)}">
<meta name="realtime-url" content="${esc(realtimeUrl)}">
<meta name="realtime-ws-url" content="${esc(realtimeWsUrl)}">
<meta name="mapbox-key" content="${esc(mapboxKey)}">
<meta name="sensor-code" content="${esc(sensorCode)}">
<meta name="sensor-name" content="${esc(sensorName)}">
`;

View File

@@ -1,9 +0,0 @@
const router = require('express').Router();
const path = require('path')
//Endpoints per controllare lo stato di un servizio di mappe da implementare poi..
router.get('/', (req, res) => {
res.sendFile(path.join(__dirname, '../tools/map/map.html'));
});
module.exports = router;