π Deploy to Devices
The DEJA deploy wizard reads your device's configuration from DEJA Cloud, generates the right config files for the device type, and (optionally) flashes the firmware. The same wizard handles all four IO device types β deja-arduino, deja-esp32, deja-esp32-wifi, and deja-mqtt.
π§© No code to write. DEJA IO includes the firmware. Plug in the board, attach your accessories, configure them in Throttle, and deploy. The firmware is built from your configuration and ships as readable source, so changing a pin is just a redeploy.
On a device's Firmware section in Throttle, the install tabs are Browser (install straight from a browser with Web Serial, such as Chrome or Edge β see Install from your browser below), CLI (deja deploy <id>, shown with your device's ID filled in) and Terminal (build and flash by hand β see Flashing By Hand below).
π¬ Running the Deploy Wizard
deja deploy
The interactive wizard walks you through:
- πΊοΈ Layout selection β pick the layout from your DEJA account
- π Device selection β pick a registered device (auto-filtered to flashable types)
- π WiFi and connection β only for
deja-esp32-wifianddeja-mqtt: keep the credentials from the previous build, or enter the SSID and password plus the MQTT broker IP β or, for WebSocket devices, the DEJA server host and port (see WebSocket devices) - π¦ Config generation β pulls in the device's configuration along with any effects, turnouts, sensors, and signals assigned to it in Throttle, and writes platform-specific config files
- β¬οΈ Build & flash β compiles the firmware (or copies CircuitPython files) and uploads to the connected board
π§° What deja deploy installs, and where
The first time you flash an Arduino or ESP32, the wizard asks once before downloading its tools. Pass --yes to accept those download questions (and the port question below) without being asked. Without a terminal and without --yes, it stops straight away instead of waiting for an answer.
--yes doesn't make deja deploy fully unattended: you still choose the deploy method and confirm or pick the serial port, and the device too unless you name it (deja deploy <deviceId>).
| What | Where | Size |
|---|---|---|
arduino-cli 1.5.1 + Arduino AVR boards (arduino:avr 1.8.6) |
~/.deja/tools/ |
about 150 MB |
ESP32 board support (esp32:esp32 3.3.8, asked separately) |
~/.deja/tools/arduino/ |
about 1.5 GB on macOS and Linux, about 1.7 GB on Windows |
| Arduino libraries: PubSubClient 2.8.0, Adafruit BusIO 1.17.4, Adafruit PWM Servo Driver 3.0.3, ArduinoJson 7.4.3, WebSockets 2.7.2, TurnoutPulser 1.0.1 | ~/.deja/tools/arduino/user/ |
small |
| π DCC-EX CommandStation-EX source (v5.6.6-Prod, EX-CSB1 only) | ~/.deja/cache/dcc-ex/ |
about 1 MB |
π ESP32 board support for DCC-EX (esp32:esp32 2.0.17, EX-CSB1 only, asked separately) |
~/.deja/arduino-dccex/ |
about 1.5 GB download, needs about 5 GB free |
DCC-EX gets its own ESP32 core, kept apart in ~/.deja/arduino-dccex/, because DCC-EX can't build on ESP32 core 3.x, which DEJA's own boards use. Having both side by side is normal. The DCC-EX source is checked against a SHA-256 written into DEJA before it is used, and a download that fails the check is thrown away.
These are DEJA's own copies, pinned to tested versions. DEJA checks the arduino-cli download against a SHA-256 written into DEJA itself before it is unpacked or run. The cores and libraries are then downloaded by arduino-cli, which checks each one against its package index (Espressif's ESP32 index is not signed). They never change an Arduino IDE you already have. Nothing needs sudo.
Using your own arduino-cli: set DEJA_ARDUINO_CLI=/path/to/arduino-cli (from a source checkout with no DEJA copy yet, an arduino-cli on your PATH is used the same way). It is your binary and your config, so DEJA does not checksum it, and DEJA's pinned cores and libraries install into your setup. The wizard prints a notice when that changes a version you had.
Generated firmware bundles are kept in ~/.deja/builds/ (readable only by your user account). They hold your WiFi password and each WebSocket device's token. deja update never touches them, so redeploying a WebSocket device keeps it paired.
On an installed copy, if the DEJA server is using the board's USB port, the wizard offers to disconnect it for the upload (the default is yes) and always reconnects it afterwards. Downloads and the compile happen first, while the server still has the board. With --yes, or when there is no terminal, it takes the default (yes) without asking. For an EX-CommandStation, trains stop until it reconnects. From a source checkout (deja deploy run from the repo, or pnpm run deploy in io/), the wizard has no link to the server, so stop the server or disconnect the device in Throttle β Devices before you flash.
After a successful flash, the wizard records lastDeployedAt and firmwareVersion on the device.
π¦ Installed copies
deja deploy runs on a normal installed copy: no source checkout, pnpm, or admin keys. It first checks that the firmware shipped with your server matches the installed version, and tells you to run deja update if it doesn't.
Boards deja deploy installs: Arduino Mega, ESP32 (USB), ESP32 (WiFi), Pico W and EX-CSB1 (EX-CommandStation or booster).
- π EX-CommandStation: an EX-CSB1 builds and flashes with
deja deploy(DEJA downloads DCC-EX v5.6.6-Prod, adds your track outputs, and compiles it). The device's Expansion setting picks the motor shield. A booster is deployed the same way. A Mega EX-CommandStation uses DCC-EX's EX-Installer. DEJA sends your track outputs to the EX-CommandStation each time the DEJA Server connects to it; to apply a change right away, disconnect and reconnect it. - π‘ LED strips (DEJA LED, WLED): these run WLED, not DEJA firmware. Install WLED with the WLED web installer, then add or connect the board in Throttle as a WLED device.
Exit codes: 0 built or flashed, 1 error, 2 cancelled. For diagnostics, run node ~/.deja/server/deploy.js --self-check.
The firmware source ships with the server, along with notices for the MIT-licensed Adafruit CircuitPython libraries it bundles. arduino-cli and the EX-CommandStation firmware (CommandStation-EX) are GPL-3.0 and are downloaded on your machine, never redistributed by DEJA.
π¦ What Gets Deployed
π’ deja-arduino (Arduino Mega over USB)
Generates config.h with:
DEVICE_IDfrom the device registered in Throttle- Feature flags based on what's configured (effects β
ENABLE_OUTPUTS, turnouts βENABLE_TURNOUTS, etc.) OUTPINS,SIGNALPINS,SENSORPINSarrays from your device's pin mappingTurnoutPulserdefinitions from your configured turnouts
Then compiles + uploads via arduino-cli against the Mega FQBN.
π deja-esp32 (ESP32 over USB)
Same config.h shape as deja-arduino (the sketch is shared) β only the build target changes. Compiles + uploads via arduino-cli against the ESP32 FQBN at 460800 baud upload speed.
π deja-esp32-wifi (ESP32 over WiFi β MQTT or WebSocket)
Generates config.h with everything deja-arduino ships plus the WiFi and transport settings baked in at build time:
WIFI_SSID,WIFI_PASSWORDβ entered during the wizardDEJA_TRANSPORT_WSβ1when the device's transport is WebSocket, else0MQTT_BROKERβ entered during the wizard (MQTT devices);MQTT_PORTis1883.MQTT_USERNAME/MQTT_PASSWORDare written empty β editconfig.hby hand if your broker needs themWS_HOST,WS_PORT,WS_TOKENβ WebSocket devices: the server host and port from the wizard, and the generated tokenLAYOUT_ID,DEVICE_ID,TOPIC_IDβ sourced from your layout's DEJA Cloud config
Then compiles + uploads against the ESP32 FQBN (with -DWEBSOCKETS_TCP_TIMEOUT=1000, so an unreachable server stalls each connect attempt for about a second rather than five). After flashing, the device connects to WiFi, then subscribes to DEJA/{LAYOUT_ID}/{DEVICE_ID} (MQTT) or opens ws://{WS_HOST}:{WS_PORT}/device (WebSocket), and starts processing commands.
π deja-mqtt (Raspberry Pi Pico W)
Generates:
settings.tomlwith WiFi credentials,TRANSPORT, the MQTT broker or WebSocket host/port/token, layout ID, and device IDconfig.jsonwith the pin mapping, Kato turnouts and sensors from your device configuration
Then copies code.py, the other firmware files, lib/, settings.toml, and config.json to the mounted CIRCUITPY drive β no compilation required.
WebSocket devices
When the device's Transport is WebSocket (ESP32 WiFi or Pico W), deja deploy asks for the DEJA server host (default: this machine's LAN IPv4) and port (default VITE_WS_PORT, else 8082) instead of an MQTT broker. It then:
- Generates a per-device token (32 random bytes, 64 hex characters) and bakes it into
config.h/settings.toml. - Saves only the token's SHA-256 hash to the device in DEJA Cloud β the server checks every connection against it.
Redeploying reuses the token from the previous bundle (if it's a valid 64-hex token), so an already-flashed board keeps working. Options:
| Flag | Env | Effect |
|---|---|---|
--ws-host <host> |
WS_HOST |
Server host to bake in. Always wins over the previous bundle and skips the prompt |
--ws-port <port> |
WS_PORT |
Server port (integer 1β65535). Always wins; an invalid value stops the deploy |
--rotate-token |
β | Issue a new token. Boards flashed with the old one are refused until you reflash them |
pnpm build:firmware (from io/) handles WebSocket devices the same way and accepts the same flags.
π Install from your browser (ESP32 WiFi and Arduino Mega)
For a deja-esp32-wifi board or a deja-arduino Arduino Mega 2560 you can skip the command line. In Throttle, open Devices, pick the device, then Firmware β Browser. Plug the board into your computer with a USB cable. Four steps take you from a blank board to an online device:
- π Plug it in β click Connect board and choose the board's USB serial port.
- π Review β check the pins, your WiFi Network and Password ("Sent over USB. Never stored.") and the DEJA server Address and Port, then click Install firmware.
- β¬οΈ Install β Throttle writes the firmware and sends the device's configuration. Don't unplug the board until it says Online, and keep the tab open.
- π’ Online β the board restarts, joins your WiFi and checks in with the server. Click Done.
This needs a browser with Web Serial, such as Chrome or Edge, on a computer, loaded over HTTPS (the hosted Throttle, or localhost). Safari and phones can't talk to USB serial, so use deja deploy above, which also works for every other device type. A browser install leaves the device status LED unlit unless you choose a pin under Status LEDs.
On an Arduino Mega 2560 there is nothing to type: Review shows the pins, and Install writes the firmware with this device's configuration already inside it, then reads it back to check. If the DEJA server has the Mega's port open, Throttle asks it to let go during the install and hands the port back afterwards. A Mega holds up to 64 outputs, 32 signal pins, 32 sensors, 24 Kato turnouts and 16 servos; for more, use deja deploy. If you build the sketch yourself in the Arduino IDE, an existing config.h keeps working and builds as a baked build; regenerate it from the device page only to pick up new settings.
π οΈ Flashing By Hand
If you'd rather flash an Arduino-family board yourself instead of letting the wizard do it, deja deploy also drops a self-contained bundle you can open in PlatformIO, Arduino CLI, or the Arduino IDE. The exact commands for your board are shown on the device's page in Throttle (Devices β the device) and in the bundle's own DEPLOYMENT.md β copy them from there rather than guessing, since they're generated per device type.
deja-mqtt (Pico W) doesn't have a manual build step β it's just CircuitPython files copied to the CIRCUITPY drive, which the wizard does for you.
Your device must be registered in Throttle (Devices) before deploying. See Devices.
π Next Steps
- π§ Arduino & ESP32 Setup β hardware setup and
config.hreference - π Pico W Setup β CircuitPython setup and
settings.tomlreference - βοΈ Configuration Reference β all generated file formats per device type