Skip to content
Andrés Cuello
Español
← All work
Case studyOpen source

RoveLink

Low-latency control of an ESP32 robot from the browser. The browser and the robot both open outbound connections to a Cloudflare Worker and Durable Object relay, so the robot needs no public IP and no open ports.

Status
Public repository on GitHub.
Built with
TypeScript · Cloudflare Workers · Durable Objects · WebSockets · ESP32
Links
Repository

Context

Driving a small robot over the internet usually means opening ports or exposing the device. RoveLink avoids both: the browser and the ESP32 each open an outbound WebSocket to a relay, and the relay only forwards messages between them.

What I built

  • A control relay on Cloudflare Workers with a Durable Object per room. It authenticates devices and controllers with shared secrets and never interprets robot physics.
  • A separate video relay (its own Worker and Durable Object) for live video, with ticket-based authorization for viewers.
  • A web dashboard in Vite, TypeScript and Tailwind. It supports the Gamepad API, a keyboard fallback and touch controls, with analog throttle and steering and a deadzone.
  • ESP32 firmware with a WSS client, TLS certificate validation against pinned root CAs, and reconnection with backoff.
  • A shared protocol package, including one differentialMix() function used by both the browser and the firmware, so the PWM shown on screen is exactly what the motors get.
  • A hardware-free demo (pnpm dev:demo) that runs the real control and video protocols against a robot simulator and a simulated camera.

Decisions

  • Latest state wins. There is no command queue, so stale input is dropped instead of replayed.
  • Safety by default: a 500 ms link watchdog stops the robot when commands stop arriving, and an emergency stop disarms it and zeroes every axis.
  • Telemetry back to the operator: RSSI, acknowledged sequence numbers and echoed throttle and steering.

Status

Open source under the Apache 2.0 license. The deployed dashboard requires an operator key.