Custom Firmware

If you already have an ESP-IDF or Arduino-ESP32 project, you don't need a starter template. Drop libscadable in, add a .scadable/ folder, push a tag.

This page is the minimum viable integration. The full Quickstart walks the exact same flow with more context.

ESP-IDF projects

1. Add the dependency

From your project root:

idf.py add-dependency "scadable/libscadable^0.2.0"

That writes dependencies.scadable/libscadable: "^0.2.0" into main/idf_component.yml. The IDF Component Registry resolves it on next build.

2. Add the four lines

In your main/main.c (or whichever file holds app_main):

#include "scadable.h"

void app_main(void) {
    wifi_up();                // your existing WiFi setup
    scadable_init(NULL);
    scadable_connect();
    scadable_publish(SCADABLE_CH_HELLO, "world", 5, 1);
    // your existing main loop continues
}

The library does not own the WiFi radio. wifi_up() is your code; the library expects a working IP stack before scadable_connect.

3. Add the .scadable/ folder

mkdir -p .scadable
cat > .scadable/config.toml <<'EOF'
target = "esp32-s3"
EOF

That's the minimum. See the folder spec for digital-twin registers and remote diagnostics.

4. Push a tag

git add .
git commit -m "Add SCADABLE"
git tag v0.1.0
git push --tags

Builds within 2 to 4 minutes (cold cache). Releases view in the dashboard shows progress.

Arduino-ESP32 / PlatformIO projects

1. Add the dependency

In platformio.ini:

[env:my_board]
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
lib_deps =
    https://github.com/scadable/libscadable.git#v0.2.0

2. Add the four lines

In src/main.cpp:

#include <Arduino.h>
#include <WiFi.h>
#include "scadable.h"

void setup() {
    WiFi.begin("ssid", "pass");           // your existing WiFi setup
    while (WiFi.status() != WL_CONNECTED) delay(100);

    scadable_init(NULL);
    scadable_connect();
    scadable_publish(SCADABLE_CH_HELLO, "world", 5, 1);
}

void loop() { /* your existing loop */ }

3. Same .scadable/ folder, same git tag flow as IDF.

The build pipeline detects PlatformIO automatically (sees platformio.ini at the repo root) and uses the PlatformIO container instead of the IDF container. Output artifact is identical.

Things to verify before tagging your first release

  • Partition table. Default IDF table works. If customized, you need factory + ota_0 + ota_1 + nvs ≥ 16 KB. Provisioner uses factory; OTA uses ota_0/ota_1; cert + WiFi in nvs.
  • Flash size. Anything < 4 MB won't fit a real customer firmware + provisioner + dual OTA slots. 4 MB is the practical minimum; 8 MB recommended.
  • PSRAM (S3). Optional, but if you have it, declare it in sdkconfig so the build pipeline picks it up. The library doesn't require it.
  • WiFi stack init. scadable_init does NOT call esp_netif_init, esp_event_loop_create_default, or any WiFi setup. You're responsible. The starter templates have a working wifi_up you can copy.

What you can't do (yet)

  • Bring your own MQTT broker. The library hard-codes the SCADABLE broker. Pointing at a self-hosted broker is roadmap (call it out if you need it).
  • Override the cert at runtime. scadable_init always reads from NVS namespace scadable_certs. If you want to use your own cert, write it to that namespace before calling scadable_init.
  • Ship without .scadable/config.toml. The build pipeline rejects repos missing it. Even a one-line file is enough.

Where to go next