diff options
| author | grothedev <grothedev@gmail.com> | 2026-05-29 21:49:20 -0400 |
|---|---|---|
| committer | grothedev <grothedev@gmail.com> | 2026-05-29 21:49:20 -0400 |
| commit | 6196004b51a6850909c154f5402ff4858eab479a (patch) | |
| tree | 126b8bb1600d0a656e0df016e25d08c390f3540e /scripts/demo-websocket-server.mjs | |
| parent | 27dc5849c3eaf4824d79938e7077abdbe2c82e24 (diff) | |
mv web stuff to root project dirHEADprototypeframeworkmain
Diffstat (limited to 'scripts/demo-websocket-server.mjs')
| -rw-r--r-- | scripts/demo-websocket-server.mjs | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/scripts/demo-websocket-server.mjs b/scripts/demo-websocket-server.mjs new file mode 100644 index 0000000..1bee865 --- /dev/null +++ b/scripts/demo-websocket-server.mjs @@ -0,0 +1,131 @@ +import { WebSocketServer } from 'ws'; + +const port = Number(process.env.PORT || 8080); +const profile = process.env.TIMEPLOT_PROFILE || 'telemetry'; +const sendIntervalMs = Number(process.env.TIMEPLOT_INTERVAL_MS || 100); +const logEvery = Number(process.env.TIMEPLOT_LOG_EVERY || 10); + +const wss = new WebSocketServer({ port }); +const startedAt = Date.now(); +let sampleIndex = 0; +let activeClientCount = 0; + +function log(message, details = '') { + const timestamp = new Date().toISOString(); + if (details) { + console.log(`[timeplot-ws ${timestamp}] ${message} ${details}`); + return; + } + + console.log(`[timeplot-ws ${timestamp}] ${message}`); +} + +function sampleTelemetry(seconds) { + return Math.sin(seconds * 2.2) + 0.35 * Math.cos(seconds * 6.4 + Math.sin(seconds * 0.8)) + 0.15 * Math.sin(seconds * 0.33); +} + +function sampleChirp(seconds) { + return 0.7 * Math.sin(seconds * seconds * 1.4) + 0.3 * Math.sin(seconds * 7.5); +} + +function sampleSteps(seconds) { + const phase = Math.floor((seconds % 8) / 1.0); + return [0, 0.4, 0.9, 1.2, 0.2, -0.6, -1.0, 0.3][phase] ?? 0; +} + +function sampleBurst(seconds) { + const burstPhase = (seconds % 6) - 1.5; + const burst = Math.sin(seconds * 9.5) * Math.exp(-(burstPhase ** 2) * 0.8); + return 0.45 * Math.sin(seconds * 2.1) + burst; +} + +function sampleValue(seconds) { + switch (profile) { + case 'chirp': + return sampleChirp(seconds); + case 'steps': + return sampleSteps(seconds); + case 'burst': + return sampleBurst(seconds); + case 'telemetry': + default: + return sampleTelemetry(seconds); + } +} + +function buildMessage() { + const timestampMs = Date.now() - startedAt; + const seconds = timestampMs / 1000; + sampleIndex += 1; + + return { + timestampMs, + value: Number(sampleValue(seconds).toFixed(6)), + sequence: sampleIndex, + profile, + }; +} + +const interval = setInterval(() => { + const message = buildMessage(); + const payload = JSON.stringify(message); + let sentCount = 0; + + for (const client of wss.clients) { + if (client.readyState === client.OPEN) { + client.send(payload); + sentCount += 1; + } + } + + if (message.sequence === 1 || (logEvery > 0 && message.sequence % logEvery === 0)) { + log( + 'broadcast', + `seq=${message.sequence} clients=${sentCount} timestampMs=${message.timestampMs} value=${message.value}`, + ); + } +}, sendIntervalMs); + +wss.on('connection', (socket, request) => { + const clientAddress = request.socket.remoteAddress || 'unknown'; + activeClientCount += 1; + log('client connected', `from=${clientAddress} activeClients=${activeClientCount}`); + + socket.send(JSON.stringify({ + timestampMs: 0, + value: 0, + sequence: 0, + profile, + message: 'connected', + })); + + socket.on('error', (error) => { + log('client error', `from=${clientAddress} error=${error.message}`); + }); + + socket.on('close', () => { + activeClientCount = Math.max(0, activeClientCount - 1); + log('client disconnected', `from=${clientAddress} activeClients=${activeClientCount}`); + }); +}); + +wss.on('error', (error) => { + log('server error', error.message); +}); + +wss.on('listening', () => { + log('listening', `url=ws://localhost:${port}`); + log('config', `profile=${profile} intervalMs=${sendIntervalMs} logEvery=${logEvery}`); +}); + +function shutdown() { + log('shutdown requested', `activeClients=${activeClientCount}`); + clearInterval(interval); + wss.close(() => { + log('server stopped'); + process.exit(0); + }); +} + +process.on('SIGINT', shutdown); +process.on('SIGTERM', shutdown); |
