BB-Eco template JSON format
This page documents the JSON file format used by bb-eco template export, bb-eco template apply, bb-eco template diff, and the desktop app's Template tab.
For the concepts behind config as code see Configuration as code with BB-Eco. For the CLI commands that read and write this format, see the bb-eco template reference.
Top-level shape
{
"identity": { /* DeviceIdentitySection — read-only, optional */ },
"network": { /* NetworkTemplateSection — DHCP, gateway, etc */ },
"device": { /* DeviceTemplateSection — name, location */ },
"security": { /* SecurityTemplateSection — credentials, MAC filter */ },
"io": { /* IoTemplateSection — ED only */ },
"serialPorts": [ /* SerialPortTemplateSection[] — ES only */ ],
"version": 1,
"family": "ED",
"compatibleModels": ["ED-588", "ED-549"],
"description": "Production ED I/O baseline — Modbus TCP, DHCP",
"createdAt": "2026-05-05T15:42:00Z"
}
Every section and every field is optional. A null field or a missing section means don't touch — BB-Eco leaves the corresponding setting on the target device unchanged.
Envelope fields
Five top-level fields describe the template itself, not the device configuration:
| Field | Type | Default | Description |
|---|---|---|---|
version | integer | 1 | Template schema version. Bumped only when the format changes incompatibly. |
family | string | null | from device on export | Target device family. "ED" or "ES". Apply will refuse to push an ED template to an ES device, and vice versa. |
compatibleModels | string[] | null | null | Optional model allowlist. If set, apply will refuse to push to a device whose model isn't in the list. Useful for templates that include settings only valid on a specific hardware variant. |
description | string | null | null | Human-readable description. Shown in the desktop app's template list and in bb-eco template validate output. |
createdAt | RFC 3339 timestamp | null | export time | When the template was generated. Informational only. |
These envelope fields are suppressed from bb-eco config <device> output but retained in bb-eco template export output.
identity — read-only device identity
Populated only when --include-identity is passed to export. Never applied by template apply. Never compared by template diff. Useful as a forensic record of which device a template came from.
"identity": {
"mac": "00:0A:4F:12:34:AB",
"ip": "192.168.1.50",
"model": "ED-588",
"modelVariant": "T",
"firmwareVersion": "8.33",
"firmwareType": "0001",
"firmwareDate": "2026-01-15"
}
| Field | Type | Description |
|---|---|---|
mac | string | Hardware MAC, colon-separated uppercase |
ip | string | Address the device was reachable at when exported |
model | string | Model number (e.g. ED-588) |
modelVariant | string | Variant suffix (T, T4, R2, R3) |
firmwareVersion | string | Running firmware version |
firmwareType | string | Numeric type code from the .efw SINF header |
firmwareDate | string | Firmware build date |
network — network configuration
"network": {
"dhcp": true,
"staticIp": null,
"subnet": "255.255.255.0",
"gateway": "192.168.1.1",
"dns": "192.168.1.1",
"webPort": 80,
"upnp": true
}
| Field | Type | Notes |
|---|---|---|
dhcp | boolean | null | If true, ignores static settings |
staticIp | string | null | Typically null in templates — IPs are device-specific |
subnet | string | null | Dotted-quad subnet mask |
gateway | string | null | Default gateway IP |
dns | string | null | Primary DNS server |
webPort | integer | null | Web server port (default 80) |
upnp | boolean | null | ED only — UPnP enabled |
network is applied last in the apply order so that an IP change can't strand the rest of the apply.
device — device-level identity settings
"device": {
"name": "Pumphouse-Sensors-01",
"location": "Pumphouse",
"checkConnectivity": true
}
| Field | Type | Notes |
|---|---|---|
name | string | null | User-facing device name |
location | string | null | Free-form location label. ED firmware caps this at 10 characters |
checkConnectivity | boolean | null | Connectivity-check feature enabled |
security — credentials and access control
Excluded from export by default. Pass --include-security to opt in for usernames, MAC filters, and auth method. Passwords stay excluded unless you also pass --include-passwords (rarely a good idea — see the warning below).
"security": {
"adminUsername": "admin",
"adminPassword": null,
"userUsername": null,
"userPassword": null,
"adminPasswordSet": true,
"userPasswordSet": false,
"adminMacFilterEnabled": false,
"adminMacAddress": null,
"userMacFilterEnabled": true,
"userMacAddresses": ["00:0A:4F:11:22:33", "00:0A:4F:44:55:66"],
"authentication": "Digest",
"resetProtection": "AdminOnly"
}
| Field | Type | Notes |
|---|---|---|
adminUsername, userUsername | string | null | Account usernames |
adminPassword, userPassword | string | null | Never commit these to Git |
adminPasswordSet, userPasswordSet | boolean | null | Read-only signals — true if device has a password set. Ignored by apply |
adminMacFilterEnabled, userMacFilterEnabled | boolean | null | MAC-based access control toggles |
adminMacAddress | string | null | Allowed admin MAC, hex (e.g. 00A04F010203) |
userMacAddresses | string[] | null | Whitelist of up to 32 user MAC addresses |
authentication | string | null | "Basic" or "Digest" |
resetProtection | string | null | "Everybody" or "AdminOnly" |
The export tool can embed passwords in the JSON when you ask it to, but storing passwords in version control is rarely the right answer. Prefer leaving adminPassword and userPassword as null in committed templates and setting them through a separate secure-secrets workflow.
io — IO protocol configuration (ED only)
"io": {
"protocol": "Modbus",
"modbusTcpPort": 502,
"modbusSlaveId": 1,
"modbusIdleTimeout": 60,
"maxConnections": 16,
"checksum": 1,
"lines": [
{
"index": 0,
"name": "Pump 1 status",
"lineType": "digitalInput",
"enabled": true
},
{
"index": 1,
"name": "Tank temperature",
"lineType": "rtd",
"enabled": true,
"sensorType": "Pt100-385",
"wiring": "3-wire",
"unit": "°C"
}
]
}
Top-level fields:
| Field | Type | Notes |
|---|---|---|
protocol | string | null | "ASCII" or "Modbus" |
dconAddress | int | null | DCON address (1-based) |
dconTcpPort | int | null | DCON TCP port (default 9500) |
maxConnections | int | null | Max simultaneous connections |
maxConnectionsPerDevice | int | null | Per-client connection cap |
idleTimeout | int | null | Idle timeout in seconds (0 = disabled) |
counterUpdate | int | null | Counter update direction code |
checksum | int | null | Checksum enabled (0/1) |
modbusTcpPort | int | null | Modbus TCP port (default 502) |
modbusSlaveId | int | null | Modbus slave ID |
modbusIdleTimeout | int | null | Modbus idle timeout |
gatewayBaudRate | int | null | Baud rate code for serial gateway |
commandTimeout | int | null | Command timeout in ms |
powerOnValues | string | null | Power-on IO line values, hex string |
safeValues | string | null | Safe-disconnect IO values, hex string |
eStopValues | string | null | E-stop IO values, hex string |
eStopLine, eStopDirection | string | null | E-stop trigger configuration |
lines | IoLineTemplateConfig[] | null | Per-line config (see below) |
Each entry in lines:
| Field | Type | Notes |
|---|---|---|
index | int | Line index (0-based). Required when present |
name | string | null | Human-readable line name |
lineType | string | null | "digitalInput", "digitalOutput", "analogInput", "analogOutput", "rtd", "thermocouple" |
enabled | boolean | null | Line enabled |
unit | string | null | Display unit ("°C", "V", "mA") |
sensorType | string | null | RTD: "Pt100-385" etc. Analog: "+/-10V", "4-20mA". Thermocouple: "K", "J", "T", etc |
wiring | string | null | RTD only: "2-wire", "3-wire", "4-wire" |
serialPorts — serial port configuration (ES only)
Array of port configurations:
"serialPorts": [
{
"index": 0,
"portMode": "RS422/485",
"overrideAppSettings": true,
"baudRate": 115200,
"dataBits": 8,
"parity": "None",
"stopBits": "One",
"flowControl": "None",
"duplex": "HalfDuplexAutoGating",
"protocol": "RawTcp",
"tcpPort": 9001,
"idleTimeout": 60,
"fifoEnabled": true,
"tunneling": {
"enabled": true,
"isMaster": false,
"remoteIp": null,
"remotePort": null
}
}
]
| Field | Type | Notes |
|---|---|---|
index | int | 0-based port index. Required when present |
portMode | string | null | "RS232" or "RS422/485" |
overrideAppSettings | boolean | null | "Always use these settings" toggle |
baudRate | int | null | Standard baud rates |
dataBits | int | null | 5, 6, 7, or 8 |
parity | string | null | "None", "Odd", "Even", "Mark", "Space" |
stopBits | string | null | "One", "OnePointFive", "Two" |
flowControl | string | null | "None", "CtsRts", "XonXoff", "DtrDsr" |
duplex | string | null | "FullDuplex", "HalfDuplexAutoGating", etc |
protocol | string | null | "RawTcp", "TelnetServer", etc |
tcpPort | int | null | TCP port for the serial protocol |
idleTimeout | int | null | Idle timeout in seconds |
fifoEnabled | boolean | null | UART FIFO buffer toggle |
tunneling | TunnelTemplateConfig | null | See below |
tunneling shape:
| Field | Type | Notes |
|---|---|---|
enabled | boolean | Tunnel mode on/off |
isMaster | boolean | True = initiates connection, false = listens |
remoteIp | string | null | Remote tunnel IP (for master) |
remotePort | int | null | Remote tunnel TCP port |
Apply order
When bb-eco template apply runs, it pushes the sections to the device in this order to avoid losing connectivity mid-apply:
device— name, location (no connection impact)security— credentials (no connection impact)io— ED line config (no connection impact)serialPorts— ES port config (no connection impact)network.webPortandnetwork.upnp— may disconnect if the web port changesnetwork.dhcp,network.staticIp,network.subnet,network.gateway,network.dns— may disconnect if the IP changes
If the device becomes unreachable after step 5 or 6, apply treats this as a successful apply (the new settings took effect — you just need to find the device at its new address).
Versioning
version: 1 covers all current templates. The version field exists so a future BB-Eco can refuse to apply templates from a newer schema and so older BB-Eco versions can warn customers about format changes. Don't bump it manually — BB-Eco writes the right value on export.
More resources
- Configuration as code with BB-Eco — concept and rationale
- Detect configuration drift with BB-Eco — task walkthrough
bb-eco templateCLI reference — every command and option