feat: udp stream
This commit is contained in:
80
test/pixelstream/bouncing-ball.js
Normal file
80
test/pixelstream/bouncing-ball.js
Normal file
@@ -0,0 +1,80 @@
|
||||
const dgram = require('dgram');
|
||||
|
||||
const host = process.argv[2];
|
||||
const port = parseInt(process.argv[3] || '4210', 10);
|
||||
const pixels = parseInt(process.argv[4] || '64', 10);
|
||||
const intervalMs = parseInt(process.argv[5] || '30', 10);
|
||||
|
||||
if (!host) {
|
||||
console.error('Usage: node bouncing-ball.js <device-ip> [port] [pixels] [interval-ms]');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const socket = dgram.createSocket('udp4');
|
||||
const isBroadcast = host === '255.255.255.255' || host.endsWith('.255');
|
||||
|
||||
let position = Math.random() * (pixels - 1);
|
||||
let velocity = randomVelocity();
|
||||
|
||||
function randomVelocity() {
|
||||
const min = 0.15;
|
||||
const max = 0.4;
|
||||
const sign = Math.random() < 0.5 ? -1 : 1;
|
||||
return (min + Math.random() * (max - min)) * sign;
|
||||
}
|
||||
|
||||
function rebound(sign) {
|
||||
velocity = randomVelocity() * sign;
|
||||
}
|
||||
|
||||
function mix(a, b, t) {
|
||||
return a + (b - a) * t;
|
||||
}
|
||||
|
||||
function generateFrame() {
|
||||
const dt = intervalMs / 1000;
|
||||
position += velocity * dt * 60; // scale velocity to 60 FPS reference
|
||||
|
||||
if (position < 0) {
|
||||
position = -position;
|
||||
rebound(1);
|
||||
} else if (position > pixels - 1) {
|
||||
position = (pixels - 1) - (position - (pixels - 1));
|
||||
rebound(-1);
|
||||
}
|
||||
|
||||
const activeIndex = Math.max(0, Math.min(pixels - 1, Math.round(position)));
|
||||
|
||||
let payload = 'RAW:';
|
||||
for (let i = 0; i < pixels; i++) {
|
||||
if (i === activeIndex) {
|
||||
payload += 'ff8000';
|
||||
continue;
|
||||
}
|
||||
|
||||
const distance = Math.abs(i - position);
|
||||
const intensity = Math.max(0, 1 - distance);
|
||||
const green = Math.round(mix(20, 200, intensity)).toString(16).padStart(2, '0');
|
||||
const blue = Math.round(mix(40, 255, intensity)).toString(16).padStart(2, '0');
|
||||
payload += '00' + green + blue;
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
function sendFrame() {
|
||||
const payload = generateFrame();
|
||||
const message = Buffer.from(payload, 'utf8');
|
||||
socket.send(message, port, host);
|
||||
}
|
||||
|
||||
setInterval(sendFrame, intervalMs);
|
||||
|
||||
if (isBroadcast) {
|
||||
socket.bind(() => {
|
||||
socket.setBroadcast(true);
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`Streaming bouncing ball pattern to ${host}:${port} with ${pixels} pixels (interval=${intervalMs}ms)`);
|
||||
|
||||
Reference in New Issue
Block a user