// WebSocket client to broadcast smooth rainbow color changes across the cluster // Usage: node ws-cluster-broadcast-rainbow.js ws:///ws const WebSocket = require('ws'); const url = process.argv[2] || 'ws://127.0.0.1/ws'; const ws = new WebSocket(url); function hsvToRgb(h, s, v) { const c = v * s; const x = c * (1 - Math.abs(((h / 60) % 2) - 1)); const m = v - c; let r = 0, g = 0, b = 0; if (h < 60) { r = c; g = x; b = 0; } else if (h < 120) { r = x; g = c; b = 0; } else if (h < 180) { r = 0; g = c; b = x; } else if (h < 240) { r = 0; g = x; b = c; } else if (h < 300) { r = x; g = 0; b = c; } else { r = c; g = 0; b = x; } const R = Math.round((r + m) * 255); const G = Math.round((g + m) * 255); const B = Math.round((b + m) * 255); return { r: R, g: G, b: B }; } function toHex({ r, g, b }) { const h = (n) => n.toString(16).padStart(2, '0').toUpperCase(); return `#${h(r)}${h(g)}${h(b)}`; } let hue = 0; const SAT = 1.0; // full saturation const VAL = 1.0; // full value const BRIGHTNESS = 80; const UPDATE_RATE = 100; // ms let timer = null; ws.on('open', () => { console.log('Connected to', url); // UPDATE_RATE ms updates (10 Hz). Be aware this can saturate slow links. timer = setInterval(() => { const rgb = hsvToRgb(hue, SAT, VAL); const color = toHex(rgb); const envelope = { event: 'api/neopattern/color', data: { color, brightness: BRIGHTNESS } }; const msg = { event: 'cluster/broadcast', payload: envelope }; try { ws.send(JSON.stringify(msg)); } catch (_) {} hue = (hue + 2) % 360; // advance hue (adjust for speed) }, UPDATE_RATE); }); ws.on('message', (data) => { // Optionally throttle logs: comment out for quieter output // console.log('WS:', data.toString()); }); ws.on('error', (err) => { console.error('WebSocket error:', err.message); }); ws.on('close', () => { if (timer) clearInterval(timer); console.log('WebSocket closed'); });