// server.js const http = require('http'); const express = require('express'); const { createClient } = require('redis'); const { Server } = require('socket.io'); const fetch = require('node-fetch'); // npm i node-fetch@2 const fs = require('fs'); const yaml = require('js-yaml'); // npm i js-yaml const path = require('path'); const app = express(); const server = http.createServer(app); const io = new Server(server); /* --------------------------------------------------------------------- */ /* ---------- 1. Load the YAML configuration file ---------------------- */ /* --------------------------------------------------------------------- */ let config = {}; try { const file = fs.readFileSync(path.resolve(__dirname, 'cosmostat_settings.yaml'), 'utf8'); config = yaml.load(file); } catch (e) { console.error('Failed to load config.yaml:', e); process.exit(1); } const API_PORT = config.custom_api_port || 5000; // fallback to 5000 const API_HOST = config.docker_gateway || '192.168.37.1'; // fallback IP const API_BASE = `http://${API_HOST}:${API_PORT}`; // --------------------------------------------------------------------- // ---------- 2. Socket.io ------------------------------------------------ // --------------------------------------------------------------------- io.on('connection', async socket => { console.log('client connected:', socket.id); // Call the external API every time a client connects try { const resp = await fetch(`${API_BASE}/start_timer`, { method: 'GET' }); const data = await resp.json(); console.log('API responded to connect:', data); } catch (err) { console.error('Failed to hit start_timer endpoint:', err); } // Listen for tableRendered event from the client socket.on('tableRendered', async () => { console.log('Client reported table rendered - starting timer'); try { const resp = await fetch(`${API_BASE}/start_timer`, { method: 'GET' }); const text = await resp.text(); console.log('Timer endpoint responded:', text); } catch (err) { console.error('Failed to hit start_timer:', err); } }); }); /* --------------------------------------------------------------------- */ /* ---------- 3. Serve static files ----------------------------------- */ /* --------------------------------------------------------------------- */ app.use(express.static('public')); /* --------------------------------------------------------------------- */ /* ---------- 4. Redis subscriber ------------------------------------- */ /* --------------------------------------------------------------------- */ const redisClient = createClient({ url: 'redis://192.168.37.1:6379' }); redisClient.on('error', err => console.error('Redis error', err)); (async () => { await redisClient.connect(); const sub = redisClient.duplicate(); // duplicate to keep separate pub/sub await sub.connect(); // Subscribe to the channel that sends host stats await sub.subscribe( ['host_metrics'], (message, channel) => { let payload; try { payload = JSON.parse(message); // message is a JSON string } catch (e) { console.error(`Failed to parse ${channel}`, e); return; } io.emit(channel, payload); } ); sub.on('error', err => console.error('Subscriber error', err)); })(); /* --------------------------------------------------------------------- */ /* ---------- 5. Start the HTTP server --------------------------------- */ /* --------------------------------------------------------------------- */ const PORT = process.env.PORT || 3000; server.listen(PORT, () => { console.log(`Server listening on http://localhost:${PORT}`); });