The Mental Model
SCADABLE has one job: take the firmware you write, build it, ship it to your fleet, and give you a dashboard to operate the devices. You never write driver code for cert enrollment, never touch MQTT plumbing, never manage signing keys. You describe what your device does in firmware; the platform does the rest.
The three layers
┌────────────────────────────────────────┐
│ Your firmware │ ← you write this
│ + libscadable │ ← you depend on this
└────────────────────────────────────────┘
│
▼ (boot → load cert → edge discover → MQTT)
┌────────────────────────────────────────┐
│ SCADABLE broker + edge router │ ← we run this
│ (mTLS-capable EMQX behind Caddy) │
└────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────┐
│ Backend + dashboard │ ← we run this
│ (build pipeline, fleet view, OTA) │
└────────────────────────────────────────┘
What you write
A SCADABLE project is your existing firmware repo plus a single tiny config file (.scadable/config.yaml) and a dependency on scadable/libscadable. Your firmware lives in C with ESP-IDF, using the structure you already use.
The library owns app_main (via a weak symbol). You define scadable_user_main instead:
#include "scadable.h"
#include "esp_wifi.h"
void scadable_user_main(void) {
my_wifi_connect(); // your code
while (1) {
do_your_thing();
vTaskDelay(pdMS_TO_TICKS(1000));
}
}That's the whole device-to-cloud surface. No paho-mqtt imports, no socket setup, no callback hell, no cert handling. The library owns the lifecycle, the broker owns the routing, the dashboard owns operations.
The build pipeline
When you push code to your bound GitHub repo, four things happen:
- Webhook. GitHub fires a webhook to SCADABLE.
- Build. SCADABLE clones at the commit SHA, picks the right ESP-IDF container based on
.scadable/config.yaml→device_type, runsidf.py build. - Publish. The artifact lands in SCADABLE's storage; a Release entry appears in the dashboard.
- Deploy (on your command). Click "Deploy" in the dashboard for any build; the library's OTA agent on online devices picks it up via MQTT, downloads, installs, restarts, and validates. Offline devices catch up on next reconnect.
Cold-cache build for a small firmware: 2–4 minutes. Incremental: under 90 seconds.
What you ship
The artifact is a single firmware binary. Devices fetch it over HTTPS using a URL embedded in the OTA command, write it to the inactive A/B partition (ota_0 or ota_1), and reboot. If the new firmware fails to boot cleanly, ESP-IDF's bootloader rolls back to the previous slot automatically.
You don't write any of the OTA download / verify / install / rollback code. The library handles it.
Why so minimal
Industrial firmware that fails in production usually fails because of side effects you didn't see coming — a callback that takes a lock you forgot, a thread that leaks when the network drops, a cert that expires at 3 AM.
The library is opinionated about all the cloud-side side effects so you can't get them wrong. Your firmware says "do my application thing"; it doesn't manage the MQTT session, the cert, the broker reconnect, the OTA download, the boot validation. The library owns those, and we test them with the rigor of a vendor SDK so you don't have to.
This means the v0.1.0 surface is tiny — three functions and an enum. That's intentional. You won't outgrow it; you'll grow into the v0.2.0+ helpers (event publishing, log forwarding, command handlers) which sit on top of the same primitives.
Targets
The library targets the full ESP32 family from day 1: esp32, esp32-s2, esp32-s3, esp32-c2, esp32-c3, esp32-c6, esp32-h2. Pick the one matching your board via .scadable/config.yaml.
Production-tested on esp32 and esp32-s3 today; the other variants compile and should work but haven't been hardware-verified yet.
Non-ESP-IDF ports (STM32, ARM Cortex, Linux gateways) are on the long-term roadmap — same wire protocol, different code path. v0.1.0 is ESP-IDF only.
Where to go next
- Quickstart: walk the full flow end-to-end.
- Library / ESP32: the v0.1.0 component documented in depth.
- BYOR Pipeline: how the build pipeline works under the hood.
