The Mental Model

The SDK has one job. Take the Python you write, validate it, and produce static config files that the gateway reads on boot. You never write driver code, never touch MQTT, never manage certificates. You describe what you want, and the gateway does the work.

What you write

A Scadable project is a directory of Python files. Devices go in devices/, controllers in controllers/, ML models in models/. Each file declares classes that describe a piece of your system.

from scadable import Device, Register, modbus_tcp, every, SECONDS

class TempSensor(Device):
    id = "temp-1"
    connection = modbus_tcp(host="192.168.1.50", port=502, slave=1)
    poll = every(5, SECONDS)
    registers = [
        Register(40001, "temperature", unit="C", scale=0.1),
    ]

That is the whole device. No imports of pymodbus, no socket setup, no callback hell. The compiler reads this declaration and produces a config file the gateway driver picks up.

The pipeline

When you run scadable compile, four things happen:

  1. Discover. The compiler walks devices/, controllers/, and models/ and lists every Python file.
  2. Parse. Each file is read as an abstract syntax tree. Class declarations get pulled out, attributes extracted. Your code is never executed at compile time.
  3. Validate. The compiler cross-checks references (controllers can only refer to devices that exist), confirms register addresses are in valid ranges, and runs target-capability checks (no dtype="float64" on RTOS).
  4. Emit. Validated declarations get written as YAML driver configs, a JSON manifest, and a bundle.tar.gz with everything inside.

What you ship

After scadable compile, your out/ directory looks like this:

out/
├── drivers/
│   ├── temp-1.yaml
│   └── pressure-1.yaml
├── manifest.json
└── bundle.tar.gz

You copy bundle.tar.gz to the gateway, restart the systemd unit, and the gateway driver subprocess starts polling. That is the full deploy.

Why declarative

Industrial code that fails in production almost always fails because of side effects you didn't see coming. A driver that crashes on a malformed packet, a callback that takes a lock you forgot, a thread that leaks when the network drops.

The SDK makes side effects impossible to write. Your Python file says "I want to read register 40001 every 5 seconds." It does not start any threads, open any sockets, or import anything that could. The gateway runtime owns all the side effects, and we test it with vendor-grade rigor so you do not have to.

Targets

The same Python compiles to artifacts for three runtime targets:

  • linux is the production target today. Runs on Raspberry Pi, industrial PCs, anything with systemd.
  • esp32 is preview. The DSL accepts the target and the validator runs full capability checks, but the runtime ships in a future release.
  • rtos is preview, same status as esp32.

You can author your project for esp32 today and scadable verify will tell you if any of your devices use protocols or data types the ESP cannot handle.

Next steps