PrabalOS
A connected ESP32 device for staying in touch
A physical device for family communication that had to keep working, unattended, from the other side of the world, so everything about it is designed around not being able to touch it again.
Problem
Moving thousands of kilometres away turns a hobby device into infrastructure. It has to stay up without physical access, survive a bad firmware flash, and be usable by people who are not going to debug it.
Every interesting decision in the project follows from that: the device has to be updatable remotely, and the update path has to be able to fail safely.
What I built
The hardware, the firmware, the backend and the control panel.
- ESP32 hardware with display, touch input, audio and physical buttons
- WiFi communication with backend APIs and device synchronisation
- Remote messaging, voice notes and drawings, with multi-sender interactions
- Discord integration
- Secure login with TOTP authentication and recovery codes
- Private blob storage and a remote firmware update flow
- Timezone handling
Designing for no physical access
Remote firmware delivery is the load-bearing feature. A device you cannot reach needs an update path that verifies what it downloaded and can roll back when the new image does not come up, which is the problem the HttpsOta library was extracted to solve.
A message reaching a device on another continent
The interesting part is not the feature. It is that every hop has to survive the device being unreachable, asleep, or on a network nobody controls.
Someone writes, draws or records a voice note
From the web control panel, or via the Discord integration.
Authenticated
TOTP, with recovery codes for the case where the authenticator is lost.
Not authenticated, the API returns 401 rather than a redirectStored
Private blob storage for drawings and voice notes; state in Redis.
The device polls and synchronises
Over WiFi, on its own schedule, the backend never assumes it is reachable.
It lands on the display
With touch, audio and physical buttons to respond.
Updating a device you cannot reach
The load-bearing feature. A failed update on a device thousands of kilometres away is the end of the device, which is why the OTA path was extracted into its own library.
A new firmware image is published
The device checks version, hash and size
Downloads to the inactive OTA slot
SHA-256 verified while downloading.
Hash mismatch or stall, nothing is installedReboots into the new image
Comes up and reports its versionDoes not, automatic rollback to the previous slot
The parts
| Layer | What is there |
|---|---|
| Device | ESP32, display, touch input, audio, physical buttons, WiFi |
| Firmware | Synchronisation, rendering, input handling, OTA client |
| Backend | APIs for messaging, voice notes, drawings and device sync; Redis state; private blob storage |
| Control panel | Web UI for sending, plus firmware delivery and device status |
| Auth | TOTP login, recovery codes, session guard on every write route |
| Integrations | Discord, and timezone handling for a device in another timezone |
Limitations and failure modes
- One deployed device. Nothing here is validated at fleet scale.
Gallery

Attribution
- Built by me
- Hardware, firmware, backend, control panel and deployment.
Related
- HttpsOta
Over-the-air updates for ESP32, over TLS, with rollback