Files
spore/test/pixelstream/snek/server.js

84 lines
2.5 KiB
JavaScript

const path = require('path');
const http = require('http');
const express = require('express');
const dgram = require('dgram');
const { WebSocketServer } = require('ws');
const HTTP_PORT = process.env.PORT || 3000;
// UDP settings
// Default broadcast; override with unicast address via UDP_ADDR if you have a single receiver
const UDP_BROADCAST_PORT = Number(process.env.UDP_PORT) || 4210;
const UDP_BROADCAST_ADDR = process.env.UDP_ADDR || '255.255.255.255';
// NeoPixel frame properties for basic validation/logging (no transformation here)
const MATRIX_WIDTH = Number(process.env.MATRIX_WIDTH) || 16;
const MATRIX_HEIGHT = Number(process.env.MATRIX_HEIGHT) || 16;
const BYTES_PER_PIXEL = 3; // GRB without alpha
const app = express();
app.use(express.static(path.join(__dirname, 'public')));
const server = http.createServer(app);
const wss = new WebSocketServer({ server, path: '/ws' });
const udpSocket = dgram.createSocket('udp4');
udpSocket.on('error', (err) => {
console.error('[UDP] error:', err);
});
udpSocket.bind(() => {
try {
udpSocket.setBroadcast(true);
console.log(`[UDP] Ready to broadcast on ${UDP_BROADCAST_ADDR}:${UDP_BROADCAST_PORT}`);
} catch (e) {
console.error('[UDP] setBroadcast failed:', e);
}
});
wss.on('connection', (ws, req) => {
const clientAddress = req?.socket?.remoteAddress || 'unknown';
console.log(`[WS] Client connected: ${clientAddress}`);
ws.on('message', (data) => {
const bufferToSend = Buffer.isBuffer(data)
? data
: (data instanceof ArrayBuffer ? Buffer.from(data) : Buffer.from(String(data)));
const expectedSize = MATRIX_WIDTH * MATRIX_HEIGHT * BYTES_PER_PIXEL;
if (bufferToSend.length !== expectedSize) {
console.warn(`[WS] Unexpected frame size: ${bufferToSend.length} bytes (expected ${expectedSize}).`);
}
const hexPayload = bufferToSend.toString('hex');
const udpPayload = Buffer.from(`RAW:${hexPayload}`, 'ascii');
udpSocket.send(
udpPayload,
UDP_BROADCAST_PORT,
UDP_BROADCAST_ADDR,
(err) => {
if (err) {
console.error('[UDP] send error:', err.message);
}
}
);
});
ws.on('close', () => {
console.log('[WS] Client disconnected');
});
ws.on('error', (err) => {
console.error('[WS] error:', err.message);
});
});
server.listen(HTTP_PORT, () => {
console.log(`Server listening on http://localhost:${HTTP_PORT}`);
});
process.on('SIGINT', () => {
console.log('Shutting down...');
try { udpSocket.close(); } catch {}
try { server.close(() => process.exit(0)); } catch {}
});