ECE-BOT can display a live MJPEG video feed from a Raspberry Pi camera directly in the operator machine view. The Pi runs a local Flask stream server and a Cloudflare Tunnel that exposes it to the internet. A helper script detects the tunnel’s public URL and posts it to ECE-BOT automatically so the dashboard always points to the current address — no manual environment variable updates required on each restart.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Kr-Yogsa/ECE-BOT/llms.txt
Use this file to discover all available pages before exploring further.
Architecture overview
Requirements
On the Raspberry Pi:| Requirement | Notes |
|---|---|
| Raspberry Pi OS (Bookworm or Bullseye) | Camera stack must be enabled |
| Camera Module (v1, v2, v3, or HQ) | Connected and detected by libcamera |
picamera2 | Python camera library |
python3-opencv | JPEG encoding for MJPEG frames |
flask | HTTP server for the stream endpoint |
cloudflared | Cloudflare Tunnel client binary |
requests | Python HTTP client for the publish helper |
| Variable | Value |
|---|---|
MACHINE_LIVE_UPDATE_TOKEN | A long random secret token shared with the Pi |
Setup
Enable and verify the camera
Update the Pi and confirm the camera is detected by A preview window should open briefly. If it fails, check that the camera cable is seated correctly and the camera interface is enabled in
libcamera:raspi-config.Install cloudflared
Download and install the Verify the install:
cloudflared binary for your Pi’s architecture. The official packages are available at https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/.For a 64-bit Pi OS:Copy the scripts to the Pi
Copy
raspberry_pi_camera_stream.py and publish_cloudflare_live_url.py from the iot/ directory of the ECE-BOT repository to the same directory on the Raspberry Pi.Set the update token in ECE-BOT
In your ECE-BOT deployment environment, set:Generate a strong token with:
Start the camera stream server
In Terminal 1 on the Pi, start the MJPEG stream server:The server starts on port 8080. You can verify the local stream from another device on the same network:The server also exposes
/health (returns {"status": "ok"}) and / (returns route info).Start the Cloudflare tunnel and publish the URL
In Terminal 2 on the Pi, run the publish helper:The script:
- Spawns
cloudflared tunnel --url http://localhost:8080. - Watches the
cloudflaredoutput for atrycloudflare.comURL. - Appends
/streamto form the full stream URL. - POSTs the URL to
POST /api/machine-live/<machine-id>/urlon ECE-BOT with the update token in theX-Live-Update-Tokenheader.
How URL priority works
ECE-BOT resolves the live stream URL in this order:- Database-stored URL — set by the
publish_cloudflare_live_url.pyscript via the API. Takes priority over all environment variables. - Machine-specific env var — e.g.
CNC_LIVE_STREAM_URLfor machine IDcnc. - Shared fallback env var —
LIVE_STREAM_URLapplied to all machines.
Static environment variables (
CNC_LIVE_STREAM_URL, LIVE_STREAM_URL) are still fully supported for deployments with a stable, permanent stream URL. Set them and skip the publish helper entirely if your tunnel URL does not change.Why auto-update matters
Cloudflare quick tunnel (trycloudflare.com) URLs are ephemeral. Every time cloudflared restarts — including after a Pi reboot — Cloudflare assigns a new random subdomain. Without the publish helper, you would need to manually update an environment variable and redeploy ECE-BOT after every restart.
The publish_cloudflare_live_url.py script eliminates that by registering the new URL automatically at startup. ECE-BOT stores it in the database and serves it immediately, with no redeploy needed.
Script reference
raspberry_pi_camera_stream.py
Starts a Flask HTTP server that captures frames from the Pi camera using picamera2 at 1280×720, encodes them as JPEG at quality 80, and serves them as an MJPEG stream at /stream.
| Endpoint | Description |
|---|---|
GET / | Returns JSON route info |
GET /health | Returns {"status": "ok"} |
GET /stream | MJPEG video stream (multipart/x-mixed-replace) |
publish_cloudflare_live_url.py
Wraps cloudflared tunnel --url http://localhost:8080, parses its stderr/stdout for the trycloudflare.com URL, and registers it with ECE-BOT.
| Argument | Default | Description |
|---|---|---|
--app-base-url | (required) | ECE-BOT public base URL |
--machine-id | cnc | Machine ID to register the stream against |
--update-token | (required) | Must match MACHINE_LIVE_UPDATE_TOKEN in ECE-BOT |
--local-service-url | http://localhost:8080 | Local server the tunnel points to |
--stream-path | /stream | Path appended to the tunnel URL |
--cloudflared-path | cloudflared | Path to the cloudflared binary |
--publish-attempts | 5 | Number of retry attempts if the POST fails |
--publish-retry-seconds | 5 | Seconds to wait between retry attempts |