import http from 'http'; import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; import { WebSocketServer } from 'ws'; import sqlite3 from 'sqlite3'; import { getRulesStatus } from './rule_engine.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const PORT = 8081; const MODEL_PICS_DIR = path.join(__dirname, 'modelPics'); // SQLite database connection (read-only for status queries) const db = new sqlite3.Database('devices.db', sqlite3.OPEN_READONLY); // WebSocket clients for broadcasting const wsClients = new Set(); // Query initial status data function getStatusData() { return new Promise((resolve, reject) => { const sql = ` SELECT d.mac, d.model, d.connected, d.last_seen, c.id as channel_id, c.component, c.field, c.type, (SELECT e.event FROM events e WHERE e.channel_id = c.id ORDER BY e.id DESC LIMIT 1) as last_event, (SELECT e.timestamp FROM events e WHERE e.channel_id = c.id ORDER BY e.id DESC LIMIT 1) as last_ts FROM devices d LEFT JOIN channels c ON c.mac = d.mac ORDER BY d.mac, c.component, c.field `; db.all(sql, [], (err, rows) => { if (err) reject(err); else { // Group by device const devices = {}; for (const row of rows) { if (!devices[row.mac]) { devices[row.mac] = { mac: row.mac, model: row.model, connected: row.connected, last_seen: row.last_seen, channels: [] }; } if (row.channel_id) { devices[row.mac].channels.push({ id: row.channel_id, component: row.component, field: row.field, type: row.type, event: row.last_event, timestamp: row.last_ts }); } } resolve(Object.values(devices)); } }); }); } // Broadcast event to all connected WebSocket clients export function broadcastEvent(mac, component, field, type, event) { const message = JSON.stringify({ type: 'event', mac, component, field, eventType: type, event, timestamp: new Date().toISOString() }); for (const client of wsClients) { if (client.readyState === 1) { // OPEN client.send(message); } } } // Broadcast rule status update to all connected WebSocket clients export function broadcastRuleUpdate(ruleName, status) { const message = JSON.stringify({ type: 'rule_update', name: ruleName, status, timestamp: new Date().toISOString() }); for (const client of wsClients) { if (client.readyState === 1) { // OPEN client.send(message); } } } // HTML Dashboard const dashboardHTML = `
Connecting...
Loading devices...