feat: Add new API endpoints and HTML pages for ML model management
- Implemented HTML pages for datasets, models, training, testing, and results. - Created API endpoints for managing repositories, results, tests, and training sessions. - Added functionality for streaming training progress via Server-Sent Events (SSE). - Introduced a Dockerfile for the ML runner with necessary dependencies. - Developed an SDK for user code execution within the runner container. - Enhanced CSS styles for improved UI layout and navigation. - Established a layout template for consistent HTML structure across pages. - Added JavaScript for dynamic interactions on the models page. - Implemented WebSocket handling for real-time communication with kiosk devices and controllers. - Implemented model registration and management API at /api/models - Added Gitea proxy API for repository interactions at /api/repos - Created results API for listing and comparing training results at /api/results - Developed training management API for enqueueing and retrieving training jobs at /api/trainings - Introduced SSE endpoint for live training progress updates - Added HTML pages for models, datasets, and training management - Created a Dockerfile for the ML runner with necessary dependencies - Developed SDK for user code execution within the runner container - Enhanced CSS styles for improved UI/UX - Implemented WebSocket communication for real-time device and controller interactions in the kiosk system
This commit is contained in:
57
realtime/src/routes/rules.js
Normal file
57
realtime/src/routes/rules.js
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Relay HTTP → WS per il push dei rulesets ai sensori.
|
||||
* Chiamato SOLO dal servizio api (internal, x-api-key).
|
||||
*
|
||||
* POST /rules/push
|
||||
* Body: { sensors: [name, ...], type, ruleset }
|
||||
* -> invia msgpack { _t: 'ruleset_update', type, ruleset } ad ogni sensore
|
||||
* online tramite la connessione WS gia' stabilita.
|
||||
*/
|
||||
|
||||
const router = require('express').Router();
|
||||
const { encode } = require('@msgpack/msgpack');
|
||||
const { connectedSensors } = require('../ws/handler');
|
||||
|
||||
const INTERNAL_KEY = process.env.INTERNAL_API_KEY;
|
||||
|
||||
function requireInternal(req, res, next) {
|
||||
const k = req.headers['x-api-key'];
|
||||
if (!INTERNAL_KEY || !k || k !== INTERNAL_KEY) {
|
||||
return res.status(403).json({ error: 'forbidden' });
|
||||
}
|
||||
next();
|
||||
}
|
||||
|
||||
router.post('/push', requireInternal, (req, res) => {
|
||||
const { sensors, type, ruleset } = req.body || {};
|
||||
if (!Array.isArray(sensors) || !sensors.length) return res.status(400).json({ error: 'sensors array required' });
|
||||
if (!type || !ruleset) return res.status(400).json({ error: 'type and ruleset required' });
|
||||
|
||||
const payload = { _t: 'ruleset_update', type, ruleset };
|
||||
let encoded;
|
||||
try {
|
||||
encoded = encode(payload);
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: `encode error: ${err.message}` });
|
||||
}
|
||||
|
||||
const pushed = [], offline = [], errors = [];
|
||||
for (const name of sensors) {
|
||||
const ws = connectedSensors.get(name);
|
||||
if (!ws || ws.readyState !== ws.OPEN) {
|
||||
offline.push(name);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
ws.send(encoded);
|
||||
pushed.push(name);
|
||||
} catch (err) {
|
||||
errors.push({ sensor: name, error: err.message });
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`[RULES] push type=${type} v=${ruleset?.version?.str || '?'} → pushed=${pushed.length} offline=${offline.length} err=${errors.length}`);
|
||||
res.json({ pushed, offline, errors });
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user