Skip to content

Conversation

@SJ7F
Copy link
Contributor

@SJ7F SJ7F commented Nov 8, 2025

Summary

Adds support for WebSocket and streaming HTTP servers as a data source. Uses the same data format as the serial connection.

Motivation & Context

Implements the suggestion in #10 as close as possible (requires HTTP headers to be added to the beginning of the TCP stream)

Changes

  • Added new HTTP/WS tab to connect modal
  • Added useHttp.ts which does pretty much exactly what useSerial.ts does but with HTTP and WebSockets instead of Serial

How to Test

To test HTTP functionality:

  1. Run the following python test code
  2. Connect to http://localhost:8080 in the HTTP/WS Stream tab
  3. Observe two sine waves being plotted
import asyncio
import math
import time

FREQ = 100  # messages per second
DT = 1 / FREQ
AMPLITUDE = 1.0
FREQ1 = 1.0  # Hz for first sine wave
FREQ2 = 0.5  # Hz for second sine wave

async def send_sine(reader, writer):
    t = 0.0
    
    try:
        writer.write(b"HTTP/1.1 200 OK\r\n")
        writer.write(b"Content-Type: text/plain; charset=utf-8\r\n")
        writer.write(b"Access-Control-Allow-Origin: *\r\n")
        writer.write(b"Cache-Control: no-cache\r\n")
        writer.write(b"Connection: keep-alive\r\n")
        writer.write(b"\r\n")
        while True:
            val1 = AMPLITUDE * math.sin(2 * math.pi * FREQ1 * t)
            val2 = AMPLITUDE * math.sin(2 * math.pi * FREQ2 * t)
            
            message = f"{val1},{val2}\n"
            writer.write(message.encode())
            await writer.drain()
            
            t += DT
            await asyncio.sleep(DT)
    except (asyncio.CancelledError, ConnectionResetError):
        print(f"client disconnected")
    finally:
        writer.close()
        await writer.wait_closed()

async def main():
    async with await asyncio.start_server(send_sine, "localhost", 8080) as server:
        addr = server.sockets[0].getsockname()
        print(f"TCP server running on {addr}")
        await server.serve_forever()

if __name__ == "__main__":
    asyncio.run(main())

To test WebSocket functionality:

  1. Run the following python test code
  2. Connect to ws://localhost:8080 in the HTTP/WS Stream tab
  3. Observe two sine waves being plotted
import asyncio
import math
import websockets

FREQ = 100  # messages per second
DT = 1 / FREQ
AMPLITUDE = 1.0
FREQ1 = 1.0  # Hz for first sine wave
FREQ2 = 0.5  # Hz for second sine wave

async def send_sine(websocket, path):
    t = 0.0
    while True:
        val1 = AMPLITUDE * math.sin(2 * math.pi * FREQ1 * t)
        val2 = AMPLITUDE * math.sin(2 * math.pi * FREQ2 * t)
        
        await websocket.send(f"{val1},{val2}")
        
        t += DT
        await asyncio.sleep(DT)

async def main():
    async with websockets.serve(send_sine, "localhost", 8080):
        print("WebSocket server running on ws://localhost:8080")
        await asyncio.Future()  # run forever

if __name__ == "__main__":
    asyncio.run(main())

Checklist

  • I ran npm run lint and fixed any issues
  • I ran npm run typecheck (TypeScript) with no errors
  • I ran npm test and tests pass
  • I ran npm run test:coverage if code paths changed significantly
  • I added/updated tests where appropriate
  • I updated docs/README if needed
  • No breaking changes without clear migration notes

Additional Notes

You cannot request resources served over an insecure protocol from a page served over HTTPS, and it is often impractical to set up TLS. @cgreening Perhaps a bundled single-file version of this web app could be provided to make it simpler for people to run locally?
I have duplicated a bit of text parsing code from useSerial.ts, it would probably be better to move that somewhere else and then call it from both useSerial.ts and useHttp.ts
I used Claude 3.5 Sonnet and GPT-5 to help write a portion of the code in this pull request.

@cgreening cgreening self-requested a review November 12, 2025 20:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant