This one is about the wire, not the chip. Nothing below changes with the board you picked, which is why the chip and language switches are not on it. They come back on the ESP32 pages this one sits underneath.
WebSocket dashboards
A page that asks the board every second is asking three thousand six hundred times an hour to be told nothing changed. A WebSocket is the same connection left open, with either end allowed to speak first.
Move both sliders. The top row is what happened; the middle row is what your code asked.
What "open" means
An HTTP request is a conversation that ends. The board asks, the server answers, both hang up — so the only way for a page to learn something new is to ask again, and the only way to learn it quickly is to ask more often.
A WebSocket starts as an ordinary HTTP request with one extra header:
GET /ws HTTP/1.1
Upgrade: websocket
Connection: UpgradeThe server answers 101 Switching Protocols and the connection simply does not
close. From that moment neither side is the client: the browser can send a
command, the board can send a reading, and each message costs about six bytes
of overhead instead of a request, a set of headers and a reply.
What it is good at, in one line each
- A dashboard. Ten sensors updating a page with no refresh button.
- A control page. A slider that moves a servo without a round trip you can feel in your hand.
- Live debug output.
Serial.printto a browser, from a board in another room.
What it costs you
A connection per client. An ESP32 running an async web server handles a handful comfortably and starts refusing at a dozen or so, because each one holds a socket and its buffers in that same small heap. If twenty people need the page, put the board behind something bigger and let that fan out.
Reconnection is your job. Wi-Fi drops, routers reboot, laptops sleep. The socket dies silently and the page keeps showing the last number it received — which is the single most misleading failure in this whole chapter. Two rules fix it:
- In the browser, reconnect on
onclosewith a growing delay, and grey the numbers out until the socket is back. - On the board, send something every 20–30 seconds even when nothing changed, so both ends can tell "quiet" from "gone".
Choosing between the three
| HTTP | MQTT | WebSocket | |
|---|---|---|---|
| Who speaks first | the board | anyone, via the broker | either end |
| Extra parts to run | none | a broker | none |
| Cost per message | high | low | lowest |
| Browser can join | yes | not directly | yes |
| Board sleeps between messages | easily | with care | no |
The row that decides most projects is the last one. A battery sensor that wakes every ten minutes should use HTTP or MQTT and go back to sleep — an open socket means an awake radio, and an awake radio is roughly 80 mA of the power budget you were trying to save. A mains-powered dashboard has no such problem, and this is the protocol it wants.
On the board
The ESP32 serves the page and the socket from the same sketch — the HTML from
flash, the socket on /ws, and a broadcast when a reading changes. That is the
async web server topic, and it is about thirty lines.
Reach it at esp32.local rather than an address that changes:
mDNS.
The board serving that page and that socket from one sketch, in about thirty lines.
Async web server →Edit this page — content/esp32/websocket-dashboards.mdx
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.