Guide

IEC 60870-5-104 (client)

Connects to an IEC 104 server as a client and maps incoming ASDUs to SCADA measurements by address.

This is the protocol reference for the IEC 104 client agent — it reads a field device's points into SCADA. To expose SCADA data back out over IEC 104, see the server agent. For everything else in the config format, see Agent configuration.

01
Driver address

Every incoming information object is joined to a configured measurement by {common_address}:{type_id}:{ioa} — an ASDU with common address 100 and a double-point object at IOA 2001 becomes 100:DP:2001. A point that isn't configured is dropped.

  • SP single point, DP double point, ST step position, BO bitstring, MEn normalized value, MEs scaled value, IT integrated totals — all discrete.
  • MEf short floating point — the only type_id that produces an analogical measurement. Rescale a discrete one with a conversion (see Agent configuration) if MEn/MEs needs engineering units.
measurement
{
  "name": "pos",
  "equipment": "bay1.brk52",
  "type": "discrete",
  "store": true,
  "driver": {
    "type": "discrete",
    "common_address": 100,
    "type_id": "DP",
    "ioa": 2001
  }
}
Commands

Same common_address/ioa, with a numeric ASDU type_id instead of the string codes above. select_common_address, select_type_id, select_ioa, and select_value are optional and add select-before-operate — omit them to operate directly. A fixed-value discrete command (45 for C_SC_NA_1, for example):

command
{
  "name": "pos.open",
  "equipment": "bay1.brk52",
  "driver": {
    "type": "discrete",
    "value": 1,
    "common_address": 100,
    "type_id": 45,
    "ioa": 2001,
    "select_common_address": 100,
    "select_type_id": 45,
    "select_ioa": 2001,
    "select_value": 0
  }
}

An analogical command carries no fixed value in the config — the setpoint comes from the command request at runtime instead (50 for C_SE_NC_1, a short floating point setpoint, for example). The same select-before-operate fields apply here too:

command
{
  "name": "setpoint",
  "equipment": "bay1.brk52",
  "driver": {
    "type": "analogical",
    "common_address": 100,
    "type_id": 50,
    "ioa": 3001
  }
}
02
Docker image

Image: khorde/iec104-agent:latest. It doesn't serve an API — the only thing on 9090 is a liveness check, GET /health (returns Healthy!) — same compose shape as every agent (see Agent configuration). Save the agent's service account key next to it, renamed to service-user.json. Its own config.yaml, pointed at your IEC 104 server:

config.yaml
iec104:
  server_utc_offset: 0
  gi_period: 10s
  client:
    address: <your-iec104-server-ip>
    port: 2404
agent:
  broker:
    ip: host.docker.internal
    port: "4222"
    tls: false
  credentials:
    url: http://auth.localhost:9310
    service_account_path: service-user.json
  command_timeout: 10s

gi_period is how often the agent sends a global interrogation; server_utc_offset (in minutes) is used when decoding the server's CP56Time2a timestamps.

Next

Agent configuration

The full schema shared by every protocol. Agent configuration.

The server counterpart

Exposing SCADA data out over IEC 104 instead of reading it in. IEC 60870-5-104 (server).

Other protocols

REST and IEC 61850 agents work the same way.

Taking this past your laptop?

Talk to us