JSON Configuration
JSON configuration is useful for field delivery: ports, unit ids, point maps, and acquisition intervals live in a file that can be changed without recompiling.
Minimal File
zeus.json:
{
"acquisition": {
"intervalMilliseconds": 500,
"pollImmediately": true
},
"channels": [
{
"name": "bus",
"type": "serial",
"options": {
"portName": "COM3",
"baudRate": 9600
}
}
],
"devices": [
{
"name": "oven",
"channel": "bus",
"type": "modbus-rtu",
"options": {
"unitId": 1
},
"points": [
{
"name": "temperature",
"options": {
"table": "holding",
"address": 0,
"scale": 0.1,
"lowAlarmLimit": 10,
"highAlarmLimit": 80
}
},
{
"name": "setpoint",
"options": {
"table": "holding",
"address": 1,
"scale": 0.1,
"writable": true
}
}
]
}
]
}
Load it:
await using var app = ZeusHost.Create(builder => builder.AddJsonFile("zeus.json"));
await app.StartAsync();
var temperature = app.Points.Get<double>("temperature");
Sections
| Section | Meaning |
|---|---|
acquisition | Polling interval and whether to poll immediately after startup |
reconnect | Automatic reconnect delay, backoff, jitter, max attempts, and circuit-break wait after channel failures |
channels | Communication lines such as serial, TCP, UDP, and virtual channels |
devices | Devices such as Modbus RTU/TCP/ASCII, Mitsubishi MC, Siemens S7, Omron FINS, Omron Host Link, EtherNet/IP, DL/T 645, IEC104, MQTT, or SNMP |
points | Business points on a device, such as temperature, setpoint, or running state |
Each device channel must reference an already declared channel name.
In the current configuration format, channel, device, and point roots only carry structural fields. Transport settings, protocol parameters, addresses, scaling, write-back, and alarms belong in each object's options. Legacy root-level fields such as channel host / portName or point address / writable fail during load.
Virtual Configuration Without Hardware
Replace a serial channel with a virtual Modbus slave:
{
"name": "bus",
"type": "virtual",
"options": {
"responder": "modbus",
"unitId": 1,
"transport": "rtu"
}
}
Set options.transport to rtu, tcp, or ascii to match the master framing. When the field device is ready, switch back to serial:
{
"name": "bus",
"type": "serial",
"options": {
"portName": "COM3",
"baudRate": 9600
}
}
Channel Fields
| Root field | Meaning |
|---|---|
name | Zeus channel name |
type | virtual, serial, tcp, tcp-server, udp, or udp-server |
startup | Startup failure mode: required is the default and aborts host startup on open failure; optional / degraded lets the host start and recover the failed channel through reconnect |
options | Channel parameters and virtual responder parameters, included in hot-reload fingerprints |
Common channels[].options:
| options field | Applies to | Meaning |
|---|---|---|
portName / baudRate | serial | COM port and baud rate. Set parity, data bits, and stop bits in code with AddSerialPort(name, options => …) |
host / port | tcp / udp | Remote host and port |
localAddress / localPort | tcp-server / udp-server | Local bind/listen settings; udp can also use localPort for a fixed local port |
responder | virtual | modbus, mc, s7, fins, host-link, mewtocol, ethernet-ip, dlt645, iec104, mqtt, or snmp |
transport | virtual | Virtual Modbus framing: rtu, tcp, or ascii; virtual FINS framing: udp or tcp |
meterAddress | virtual + dlt645 | DL/T 645 virtual meter address, 12 decimal digits |
commonAddress | virtual + iec104 | IEC104 virtual station common address, default 1 |
snmpCommunity / snmpWriteCommunity | virtual + snmp | SNMP virtual Agent read/write communities |
Device Fields
| Root field | Meaning |
|---|---|
name | Zeus device name |
channel | Channel name to bind |
type | modbus-rtu, modbus-tcp, modbus-ascii, mitsubishi-mc, siemens-s7, omron-fins, omron-host-link, panasonic-mewtocol, ethernet-ip, dlt645, iec104, mqtt, or snmp |
options | Protocol parameters, included in device hot-reload fingerprints |
points | Periodically acquired points |
Common devices[].options:
| options field | Meaning |
|---|---|
transport | FINS framing: udp or tcp, default udp |
unitId | Modbus unit id, Host Link unit number, or MEWTOCOL station number |
frameType / encoding | Mitsubishi MC frame and encoding |
| MC routing fields | networkNumber, pcNumber, ioNumber, stationNumber, monitoringTimer, and serialNumber |
| S7 fields | rack, slot, localTsap, remoteTsap, and requestedPduLength |
| FINS routing fields | Destination/source addressing, gateway, ICF, and TCP node handshake settings |
wordOrder | FINS / Host Link / MEWTOCOL 32-bit value word order |
| DL/T 645 fields | meterAddress, wakeUpPreambleCount, password, and operatorCode |
| IEC104 fields | commonAddress, originatorAddress, and interrogationQualifier |
| MQTT connection fields | Client id, credentials, keep-alive, clean session, will, packet size, keep-alive, and reconnect settings |
| SNMP fields | snmpCommunity, snmpWriteCommunity, and snmpInitialRequestId |
Point Fields
| Root field | Meaning |
|---|---|
name | Point name |
options | Point address, type, scaling, alarm, and write-back parameters, included in point fingerprints |
Common points[].options:
| options field | Meaning |
|---|---|
topic | MQTT topic; defaults to the point name and cannot contain + or # |
mqttQos / mqttRetain | MQTT subscription/write-back QoS and retained write-back setting |
table | Modbus table: holding, input, coil, or discrete |
deviceCode | Mitsubishi MC device code: D, M, X, Y, W, R, ZR |
area | S7/FINS/Host Link/MEWTOCOL area |
tag | EtherNet/IP tag path |
dataType | Protocol-specific point type; IEC104 supports single-point, normalized, scaled, and short-float; MQTT supports text, boolean, int32, int64, double, and bytes |
dataLength | DL/T 645 data payload length, excluding the 4-byte DI |
address | 0-based address; DL/T 645 DI or IEC104 IOA; strings such as "0x10" are accepted where applicable |
bit | Bit offset for bit points |
scale | Engineering scale for numeric points |
lowAlarmLimit / highAlarmLimit | Alarm thresholds after scaling |
writable | Enables write-back by point name; write it as options.writable in JSON |
Hot Reloaded Changes
By default, AddJsonFile(path, watch: true) watches the file. After save, Zeus runs ReloadAsync: acquisition interval and reconnect options are written into the running option singletons, and channels/devices are added, removed, or rebuilt from the diff.
| Change | Takes effect immediately | Notes |
|---|---|---|
acquisition.intervalMilliseconds | Yes | The next acquisition round uses the new interval |
acquisition.pollImmediately | Yes | Stored in options; affects the first round after a later restart |
reconnect.* | Yes | The next reconnect backoff uses the new values |
channels[].startup / channels[].options | Yes | Startup policy or extended option changes rebuild the same-named channel |
| COM port, baud rate, TCP/UDP address | Yes | The old channel is closed and a new instance is registered |
| Added/removed channels, devices, or points | Yes | Synchronized by name |
devices[].options / points[].options | Yes | Extended option changes rebuild the device so protocol plugins reread parameters |
Slave/unit address fields such as unitId, meterAddress, or commonAddress | Yes | The device is rebuilt |
Changing channel parameters creates a new channel instance. DataReceived, StateChanged, and PacketTraced subscriptions attached to the old instance are migrated to the new channel with the same name. If application code keeps an old IChannel reference, call Channels.Get again after hot reload.
If JSON syntax is invalid, Zeus keeps the last valid configuration and logs the error. If you do not want file watching, call await app.ReloadAsync(path) manually. When only the acquisition interval changes and topology is unchanged, ReloadAsync keeps the device instances.
When you call ReloadAsync(path, cancellationToken) manually and the token is already canceled, Zeus returns cancellation before writing new acquisition intervals, reconnect options, or topology changes. If hot reload fails partway through, Zeus tries to restore the previous valid topology; for plain JSON syntax errors, the file watcher logs a warning and keeps the current configuration.
Reconnect Options
"reconnect": {
"enabled": true,
"initialDelayMilliseconds": 1000,
"maxDelayMilliseconds": 30000,
"backoffMultiplier": 2,
"maxAttempts": 0,
"jitterRatio": 0.2,
"circuitBreakMilliseconds": 0
}
maxAttempts: 0 means unlimited attempts. A positive value stops reconnect after the limit, or enters the configured circuit-break wait before starting over when circuitBreakMilliseconds is greater than zero. jitterRatio spreads reconnect traffic after shared network failures; 0.1 to 0.3 is a practical field range.
Host Link Example
{
"channels": [
{
"name": "host-link",
"type": "serial",
"options": {
"portName": "COM3",
"baudRate": 9600
}
}
],
"devices": [
{
"name": "plc",
"channel": "host-link",
"type": "omron-host-link",
"options": {
"unitId": 0
},
"points": [
{
"name": "temperature",
"options": {
"area": "dm",
"address": 100,
"dataType": "word",
"scale": 0.1,
"writable": true
}
},
{
"name": "running",
"options": {
"area": "cio",
"address": 10,
"bit": 0,
"dataType": "bit",
"writable": true
}
}
]
}
]
}
Virtual Host Link PLC:
{
"name": "host-link",
"type": "virtual",
"options": {
"responder": "host-link",
"unitId": 0
}
}
IEC104 Example
Real station over TCP:
{
"channels": [
{
"name": "iec-link",
"type": "tcp",
"options": {
"host": "192.168.1.20",
"port": 2404
}
}
],
"devices": [
{
"name": "station",
"channel": "iec-link",
"type": "iec104",
"options": {
"commonAddress": 7
},
"points": [
{
"name": "running",
"options": {
"address": 1,
"dataType": "single-point",
"writable": true
}
},
{
"name": "temperature",
"options": {
"address": 100,
"dataType": "scaled",
"scale": 0.1,
"writable": true
}
},
{
"name": "pressure",
"options": {
"address": 200,
"dataType": "short-float"
}
}
]
}
]
}
Virtual station:
{
"channels": [
{
"name": "iec-link",
"type": "virtual",
"options": {
"responder": "iec104",
"commonAddress": 7
}
}
],
"devices": [
{
"name": "station",
"channel": "iec-link",
"type": "iec104",
"options": {
"commonAddress": 7
},
"points": [
{
"name": "running",
"options": {
"address": 1,
"dataType": "single-point",
"writable": true
}
},
{
"name": "temperature",
"options": {
"address": 100,
"dataType": "scaled",
"scale": 0.1,
"writable": true
}
},
{
"name": "pressure",
"options": {
"address": 200,
"dataType": "short-float"
}
}
]
}
]
}
IEC104 address is the three-byte IOA. single-point writes use single commands; normalized, scaled, and short-float write-back uses the matching setpoint command.
Sample JSON files live under samples/Zeus.Samples.Console.Config; copy zeus-modbus-ascii.json, zeus-dlt645.json, or zeus-iec104.json for protocol-specific examples.