const mqtt = require('mqtt'); const express = require('express'); const WebSocket = require('ws'); const fs = require('fs'); const path = require('path'); const app = express(); const port = 3001; const brokerUrl = 'mqtt://localhost'; // Replace with your broker's URL const client = mqtt.connect(brokerUrl); const mainTopic = 'apu_tb'; const nodeData = Array.from({ length: 5 }, () => Array(5).fill(null)); const nodeLastActive = {}; // Track the last active timestamp for each node // Define the path to the script const scriptPath = path.join(__dirname, 'node_addresses.sh'); // Read the bash script const scriptContent = fs.readFileSync(scriptPath, 'utf8'); app.post('public/index.html') // Serve static files from the template's public folder app.use(express.static(path.join(__dirname, 'public'))); // app.use(express.static(__dirname)); // Route to serve the main dashboard HTML file app.get('/', (req, res) => { res.sendFile(path.join(__dirname, 'public/index.html')); }); // Example API endpoint for dashboard data app.get('/api/data', (req, res) => { res.json({ users: 150, sales: 2500, revenue: 50000, active_sessions: 45 }); }); const server = require('http').createServer(app); const ws = new WebSocket.Server({ server }); // Start the server server.listen(port, () => { console.log(`Server running at http://localhost:${port}`); }); // Function to parse associative arrays from the bash script function parseAssociativeArray(script, arrayName) { const regex = new RegExp(`declare -A ${arrayName}\\s*=\\s*\\(([^)]+)\\)`, 's'); const match = script.match(regex); if (!match) return {}; const entries = match[1].trim().split('\n').map(line => line.trim()).filter(line => line.startsWith('["')); const obj = {}; entries.forEach(entry => { const parts = entry.match(/\["(.+?)"\]="(.+?)"/); if (parts) { obj[parts[1]] = parts[2]; } }); return obj; } const mesh0MAC = parseAssociativeArray(scriptContent, 'phy0MAC'); const mesh1MAC = parseAssociativeArray(scriptContent, 'phy1MAC'); // console.log(mesh0MAC); // console.log(mesh1MAC); function broadcastNodeData() { const nodeStatus = generateNodeStatus(); const message = JSON.stringify({ nodeData, nodeStatus }); // Send to WebSocket clients ws.clients.forEach(client => { if (client.readyState === WebSocket.OPEN) { client.send(message); } }); } // Function to generate status colors based on activity function generateNodeStatus() { const now = Date.now(); return nodeData.map((row, y) => row.map((cell, x) => nodeLastActive[`${y},${x}`] && (now - nodeLastActive[`${y},${x}`] < 60000) ? "lightgreen" : "lightcoral" ) ); } client.on('connect', () => { console.log('Connected to MQTT broker'); client.subscribe(`${mainTopic}/#`, (err) => { if (!err) { console.log(`Subscribed to all subtopics of: ${mainTopic}`); } else { console.error('Subscription error:', err); } }); }); client.on('message', (topic, message) => { try { const payload = JSON.parse(message.toString()); if (Array.isArray(payload) && payload.length === 2) { const data = payload[0]; const metadata = payload[1]; const { uptime, cpu_temp, mem_util, cpu_util, XPosition, YPosition, mesh0_neighbors, mesh1_neighbors } = data; const { id } = metadata; if (XPosition >= 0 && XPosition < 5 && YPosition >= 0 && YPosition < 5) { // nodeData[YPosition][XPosition] = `ID: ${id}
Temp: ${cpu_temp}°C
CUtil: ${cpu_util}
MUtil: ${mem_util}
UpTime: ${uptime}`; nodeData[YPosition][XPosition] = { id, cpu_temp, mem_util, cpu_util, uptime, mesh0_neighbors, mesh1_neighbors }; // console.log("MAC Links:", JSON.stringify(mesh0_neighbors, null, 2)); // Update the last active timestamp for the node nodeLastActive[`${YPosition},${XPosition}`] = Date.now(); // console.log(`Node data updated for ID ${id} at position (${XPosition}, ${YPosition})`); // Broadcast updated data and statuses // broadcastNodeData(); // console.log("Checkboxes known:", checkedNodeInfo); // Use this array in your app } } else { console.error('Unexpected payload format:', payload); } } catch (err) { console.error('Failed to process message:', err); } }); // Periodically broadcast the node status setInterval(() => { broadcastNodeData(); }, 1000);