Edge config document¶
This page lists every field you can set in an Edge's configuration, for use on a template's JSON tab and in Overrides JSON on a group or an Edge.
The complete configuration an Edge receives is a JSON document of type wt.config.device/v1. Preview render on an Edge's Config tab shows it. A template or an override contains only the fields it sets. See Edge configuration for how layers combine.
Top-level keys¶
The complete document has exactly these six keys. No other keys are allowed.
| Key | Type | Default when no layer sets it | Purpose |
|---|---|---|---|
schema |
string, always "wt.config.device/v1" |
"wt.config.device/v1" |
Document type. |
agent |
object | see agent |
Log level, offline storage and change confirmation. |
assets |
object | {"schema":"wt.config.assets/v1","assets":[]} |
Devices the Edge reads and their metrics. |
lan_reach |
object | {"whitelist":[]} |
Devices operators may reach through the Edge. |
app_access |
array | [] |
Filled by Watchtower from access grants. Do not set it. |
update_policy |
object or null |
null |
Agent update policy. null turns updates off. |
Watchtower fills a default only for a key that no layer sets. A key that any layer sets must be complete after the layers combine.
agent¶
All three fields are required when you set agent. The template's Agent tab writes them all.
| Field | Type | Allowed | Default | Agent tab label |
|---|---|---|---|---|
log_level |
string | error, warn, info, debug, trace |
info |
Log level |
telemetry.outbox_max_mb |
integer | 1 to 10240 | 256 | Outbox max MB |
telemetry.outbox_max_age_hours |
integer | 1 to 8760 | 168 | Outbox max age hours |
commit_confirm.timeout_s |
integer | 1 to 86400 | 120 | Confirm timeout seconds |
commit_confirm.rollback_on_connector_failure |
boolean | true, false |
false |
Roll back when a connector fails |
telemetry and commit_confirm each need both of their fields. The effective document can also show an agent.endpoints object, which Watchtower manages. Do not set it.
assets¶
| Field | Type | Required | Rules |
|---|---|---|---|
schema |
string, always "wt.config.assets/v1" |
Yes | Document type. |
defaults.batch_interval_ms |
integer | No | 100 to 60000. Default 5000. How often readings are sent in a batch. |
defaults.report |
object | No | Default report mode for all metrics. |
assets |
array | Yes | At most 64 assets. asset_id must be unique. |
Asset¶
| Field | Type | Required | Rules |
|---|---|---|---|
asset_id |
string | Yes | Lowercase letters, digits and hyphens, 2 to 63 characters, starting with a letter or digit. |
name |
string | Yes | 1 to 128 characters. |
enabled |
boolean | No | Default true. A disabled asset is not read, and its metrics do not count as tags. |
protocol |
string | Yes | opcua, modbus-tcp, sparkplug-b, s7, enip or simulator. |
connection |
object | Yes | See Protocols. |
collection |
object | No (required for sparkplug-b) |
See Protocols. |
batch_interval_ms |
integer | No | 100 to 60000. Overrides defaults.batch_interval_ms. |
metrics |
array | Yes | At most 5000 per asset and 10000 per Edge. |
Metric¶
| Field | Type | Required | Rules |
|---|---|---|---|
name |
string | Yes | Up to 64 characters: lowercase letters, digits, _, . and -, starting with a letter or digit. Unique within the asset. |
source |
object | Yes | The address on the device. See Protocols. |
data_type |
string | For modbus-tcp, s7 and enip |
bool, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float32, float64, string, datetime, bytes, json. |
unit |
string | No | Up to 32 characters. |
description |
string | No | Up to 256 characters. |
report |
object | No | Overrides the default report mode. |
Report modes¶
| Value | Behaviour |
|---|---|
{"mode":"always"} |
Send every reading. |
{"mode":"on_change","deadband":0,"max_silence_ms":60000} |
Send when the value changes by more than deadband (at least 0, default 0), when its quality changes, or after max_silence_ms without a send (at least 1000, default 60000). |
Protocols¶
opcua¶
| Part | Field | Rules and default |
|---|---|---|
connection |
endpoint_url |
Required. Starts with opc.tcp://. |
security_mode |
none, sign, sign_encrypt. Default sign_encrypt. |
|
security_policy |
None, Basic256Sha256, Aes128_Sha256_RsaOaep, Aes256_Sha256_RsaPss. Default Basic256Sha256. |
|
auth |
{"type":"anonymous"} (default) or {"type":"username","username":"…","password":<secret>}. |
|
trust |
{"mode":"tofu"} (default: trust the server certificate on first use) or {"mode":"pinned","thumbprints":["<40 hex characters>"]}. |
|
session_timeout_ms |
At least 1000. Default 60000. | |
collection |
subscription | {"mode":"subscription","publishing_interval_ms":1000,"sampling_interval_ms":null,"queue_size":1}. Intervals at least 100. queue_size at least 1. |
| polling | {"mode":"polling","interval_ms":1000}. interval_ms at least 100. |
|
source |
node_id |
Required, for example ns=2;s=Filler.Temp. |
sampling_interval_ms |
Optional, at least 100. |
modbus-tcp¶
| Part | Field | Rules and default |
|---|---|---|
connection |
host |
Required. |
port |
1 to 65535. Default 502. | |
unit_id |
0 to 255. Default 1. | |
timeout_ms |
100 to 30000. Default 1000. | |
collection |
interval_ms |
At least 100. Default 1000. |
max_registers_per_read |
1 to 125. Default 125. | |
max_bits_per_read |
1 to 2000. Default 2000. | |
max_gap |
0 to 100. Default 10. | |
inter_request_delay_ms |
0 to 1000. Default 0. | |
source |
table |
Required. coil, discrete_input, holding_register, input_register. |
address |
Required. 0 to 65535, zero-based: register 40001 is address 0. | |
bit |
0 to 15. Reads one bit of a register as bool. |
|
word_order, byte_order |
big (default) or little. |
|
length |
1 to 125 registers. Required for string. |
|
scale, offset |
Numbers. Defaults 1 and 0. |
data_type must be bool, int16, uint16, int32, uint32, int64, uint64, float32, float64 or string. Coils and discrete inputs need bool. bool on a register needs bit.
sparkplug-b¶
| Part | Field | Rules and default |
|---|---|---|
connection |
broker |
Required. Embedded broker on the Edge: {"mode":"embedded","listen":"0.0.0.0:1883","users":[{"username":"…","password":<secret>}]}, at least one user. Existing broker: {"mode":"external","url":"mqtts://…","username":"…","password":<secret>,"ca_pem":null}, url starting with mqtt:// or mqtts://. |
primary_host_id |
Optional string or null. |
|
request_rebirth |
Boolean. Default true. |
|
collection |
group_id, edge_node_id |
Required. |
device_id |
Optional. Leave it out for node-level metrics. | |
source |
metric |
Required. The metric name exactly as the device publishes it. |
s7¶
| Part | Field | Rules and default |
|---|---|---|
connection |
host |
Required. |
rack |
0 to 7. Default 0. | |
slot |
0 to 31. Default 1 (S7-1200 and S7-1500). S7-300 usually uses 2. | |
connection_type |
pg (default), op, s7_basic. |
|
password |
Optional secret, only if the CPU is password-protected. | |
port |
1 to 65535. Default 102. | |
timeout_ms |
100 to 60000. Default 2000. | |
collection |
interval_ms |
At least 100. Default 1000. |
max_items_per_read |
1 to 20. Default 20. | |
source |
address |
Required, for example DB10.DBD4, DB10.DBX0.3, MB4, I0.0. |
For data blocks on S7-1200 and S7-1500, enable PUT/GET access and turn off optimized block access in the PLC project.
enip¶
| Part | Field | Rules and default |
|---|---|---|
connection |
host |
Required. Use host:port for a non-default port. |
plc |
Required. controllogix, compactlogix, micro800, micrologix, plc5, slc500, omron-njnx. |
|
path |
Default 1,0. Empty string for Micro800. |
|
timeout_ms |
100 to 60000. Default 2000. | |
collection |
interval_ms |
At least 100. Default 1000. |
source |
tag |
Required, for example MyArray[3] or Udt.Field. PLC-5 and SLC 500 use addresses such as N7:0. |
elem_count |
At least 1. Default 1. |
simulator¶
| Part | Field | Rules and default |
|---|---|---|
connection |
Empty object {}. |
|
collection |
interval_ms |
100 to 60000. Default 1000. |
seed |
Optional integer. | |
source |
kind |
sine (default), counter, random, toggle, constant. |
period_ms |
At least 100. Default 60000. | |
min, max |
Numbers. Defaults 0 and 100. | |
value |
Fixed value for constant. |
Secrets¶
Wherever a field takes a password, write a secret reference instead of the value:
Watchtower rejects any configuration that contains a password in plain text. See Edge configuration.
lan_reach¶
| Field | Type | Rules |
|---|---|---|
whitelist |
array | Required. Each entry has exactly these four fields. |
whitelist[].id |
string | Lowercase letters, digits and hyphens, up to 63 characters. Unique. |
whitelist[].ip |
string | IPv4 address. |
whitelist[].port |
integer | 1 to 65535. |
whitelist[].label |
string | 1 to 128 characters. |
See LAN Reach.
app_access¶
Watchtower builds this list from active access grants and replaces anything a layer sets. Manage it with Grant access to an Edge.
update_policy¶
null turns agent updates off. Otherwise all three fields are required:
| Field | Type | Rules |
|---|---|---|
mode |
string | auto, download_only or manual. |
window.days |
array | At least one of sun, mon, tue, wed, thu, fri, sat. |
window.start, window.end |
string | 24-hour HH:MM. If end is earlier than start, the window runs past midnight. |
window.tz |
string | Time zone name, for example Europe/Berlin. |
allowed_registry |
string | The image repository the Edge accepts updates from. |
See Updates.
Complete example¶
A complete document with an OPC UA asset, a Modbus TCP asset, a LAN Reach entry and an update policy:
{
"schema": "wt.config.device/v1",
"agent": {
"log_level": "info",
"telemetry": { "outbox_max_mb": 256, "outbox_max_age_hours": 168 },
"commit_confirm": { "timeout_s": 120, "rollback_on_connector_failure": false }
},
"assets": {
"schema": "wt.config.assets/v1",
"defaults": {
"batch_interval_ms": 5000,
"report": { "mode": "on_change", "deadband": 0, "max_silence_ms": 60000 }
},
"assets": [
{
"asset_id": "filler-opcua",
"name": "Filler OPC UA server",
"protocol": "opcua",
"connection": {
"endpoint_url": "opc.tcp://192.0.2.21:4840",
"security_mode": "sign_encrypt",
"security_policy": "Basic256Sha256",
"auth": {
"type": "username",
"username": "edge",
"password": { "secret": { "ref": "sec_4fK2pQ9xLm7Rt1Vb" } }
},
"trust": { "mode": "tofu" }
},
"collection": { "mode": "subscription", "publishing_interval_ms": 1000 },
"metrics": [
{ "name": "filler.temp", "source": { "node_id": "ns=2;s=Filler.Temp" }, "unit": "°C" },
{ "name": "filler.running", "source": { "node_id": "ns=2;s=Filler.Running" }, "report": { "mode": "always" } }
]
},
{
"asset_id": "tank-plc",
"name": "Tank PLC",
"protocol": "modbus-tcp",
"connection": { "host": "192.0.2.20", "port": 502, "unit_id": 1 },
"collection": { "interval_ms": 1000 },
"batch_interval_ms": 2000,
"metrics": [
{
"name": "tank_level",
"source": { "table": "holding_register", "address": 0 },
"data_type": "uint16",
"unit": "%"
},
{
"name": "flow_rate",
"source": { "table": "holding_register", "address": 10, "scale": 0.1 },
"data_type": "float32",
"unit": "m3/h",
"report": { "mode": "on_change", "deadband": 0.5, "max_silence_ms": 30000 }
}
]
}
]
},
"lan_reach": {
"whitelist": [
{ "id": "hmi-web", "ip": "192.0.2.10", "port": 443, "label": "HMI web UI" }
]
},
"app_access": [],
"update_policy": {
"mode": "auto",
"window": { "days": ["sat", "sun"], "start": "02:00", "end": "05:00", "tz": "Europe/Berlin" },
"allowed_registry": "ghcr.io/privitty/privitty-edge"
}
}
In a template or an override, include only the sections you want to set, and leave out app_access.
When Watchtower refuses a configuration¶
Watchtower checks each Edge's complete document before it sends it. If a check fails, the Edge keeps its current configuration and the error appears when you hover the Sync cell on the Edges page. Preview render shows the same problems in advance. Watchtower refuses a document when:
- A field breaks a rule on this page. The error names the field by its path, such as
/assets/assets/0/asset_id. - An
asset_idor a metric name inside one asset appears twice, or the Edge exceeds 64 assets or 10000 metrics. - The Edge does not support a protocol you use:
Edge agent does not support <protocol>. Check Capabilities on the Edge's Overview tab. - The change would exceed the tag limit of your plan:
tag_cap_reached total=<n> cap=<m>. See Billing and usage.