Skip to content
EtherCAT Diagnostics

EtherCAT Diagnostics

Real-time EtherCAT fieldbus diagnostics — master state, slave health, error counters, and frame statistics. Exposes the same data as Beckhoff TE2000 HMI EtherCAT Diagnostics, but as a REST + SignalR API.

Feature flag: EtherCatDiagnostics (disabled by default)

Multi-Master Support

A PLC can have multiple EtherCAT masters. The API scopes all slave/sync-unit endpoints under a specific master.

GET /api/plcs/{plcId}/ethercat/masters                              List masters
GET /api/plcs/{plcId}/ethercat/masters/{masterId}                   Master detail
GET /api/plcs/{plcId}/ethercat/masters/{masterId}/slaves            Slave list
GET /api/plcs/{plcId}/ethercat/masters/{masterId}/slaves/{address}  Slave detail
POST /api/plcs/{plcId}/ethercat/masters/{masterId}/slaves/{address}/reset-error-counters
GET /api/plcs/{plcId}/ethercat/masters/{masterId}/syncunits         Sync units

List Masters

GET /api/plcs/{plcId}/ethercat/masters

Returns all EtherCAT masters discovered for this PLC. The master’s AMS NetId is derived from the PLC’s NetId (typically byte 5 differs, e.g., PLC=192.168.1.136.1.1 → master=192.168.1.136.3.1).

{
  "data": [
    {
      "deviceId": 0,
      "name": "EtherCAT Master 0",
      "amsNetId": "192.168.1.136.3.1",
      "currentState": "Op",
      "requestedState": "Op",
      "slaveCount": 3
    }
  ]
}
FieldDescription
deviceIdInteger ID used in URL path ({masterId})
currentStateEtherCAT state: Init, PreOp, Bootstrap, SafeOp, Op
slaveCountNumber of configured slaves

Master Detail

GET /api/plcs/{plcId}/ethercat/masters/{masterId}

Includes frame statistics.

{
  "data": {
    "deviceId": 0,
    "name": "EtherCAT Master 0",
    "amsNetId": "192.168.1.136.3.1",
    "currentState": "Op",
    "requestedState": "Op",
    "slaveCount": 3,
    "frameStatistics": {
      "cyclicSendFrames": 2033684256,
      "queuedSendFrames": 312674,
      "cyclicLostFrames": 0,
      "queuedLostFrames": 52167,
      "cyclicFramesPerSecond": 0,
      "queuedFramesPerSecond": 0,
      "cyclicTxRxErrors": 0,
      "queuedTxRxErrors": 0
    }
  }
}

List Slaves

GET /api/plcs/{plcId}/ethercat/masters/{masterId}/slaves

Returns all configured slaves with their state and device type. Device names are decoded from the Beckhoff product code (e.g., EK1100, EL2808).

{
  "data": [
    {
      "physicalAddress": 1001,
      "autoIncrementAddress": 0,
      "name": "EK1100",
      "type": "EK1100",
      "currentState": "Op",
      "requestedState": "Op",
      "isPresent": true,
      "hasError": false,
      "isDisabled": false,
      "identityMatch": true,
      "crcErrorSum": 0
    }
  ]
}
FieldDescription
physicalAddressEtherCAT fixed address (used in URL as {address})
nameUser-assigned name or decoded device type (e.g., EK1100); falls back to Slave {addr} for unknown vendors
typeHardware type derived from product code (e.g., EK1100, EL2808) — always reflects the physical device series
currentStateEtherCAT state of this slave
isPresentPhysically present on the bus
hasErrorSlave is signaling an error
crcErrorSumTotal CRC errors across all ports

Slave Detail

GET /api/plcs/{plcId}/ethercat/masters/{masterId}/slaves/{address}

Full slave detail including device identity, error counters, and port diagnostics.

{
  "data": {
    "physicalAddress": 1001,
    "name": "EK1100",
    "type": "EK1100",
    "configuredIdentity": {
      "vendorId": 2,
      "productCode": 72100946,
      "revisionNumber": 1179648,
      "serialNumber": 0
    },
    "scannedIdentity": { ... },
    "currentState": "Op",
    "isPresent": true,
    "hasError": false,
    "initError": false,
    "errorCounters": {
      "crcErrorSum": 0,
      "abnormalStateChanges": 0,
      "connectionLosses": 0
    },
    "ports": [
      {
        "port": "A",
        "physic": "EBus",
        "configured": true,
        "linkState": true,
        "crcErrorCount": 0,
        "forwardedCrcErrors": 0,
        "lostLinkCount": 0
      }
    ]
  }
}

Beckhoff Product Code Decoding

For Beckhoff devices (vendor ID 2), the product code encodes the device type:

  • Upper 16 bits = terminal number (e.g., 0x044C = 1100)
  • Lower 16 bits = device family (0x2C52 = EK coupler, 0x3052 = EL terminal, 0x4052 = EP box)

Reset Error Counters

POST /api/plcs/{plcId}/ethercat/masters/{masterId}/slaves/{address}/reset-error-counters

Resets CRC and frame counters. Requires WriteAccess policy (operator/admin + ads:write scope).

Returns 204 No Content on success.

Real-Time Notifications (SignalR)

Hub: /api/plcs/{plcId}/ethercat/ws

Requires ReadAccess policy. JWT via ?access_token= query string.

On connect, the client is automatically subscribed to all EtherCAT events for that PLC. Events are broadcast to all connected clients.

EventPayloadDescription
MasterStateChanged{ masterId, masterName, currentState, previousState, requestedState }Master state transition
SlaveStateChanged{ masterId, address, name, currentState, previousState, hasError }Slave state change
SlavePresenceChanged{ masterId, address, name, isPresent }Slave appeared/disappeared
CrcErrorThresholdExceeded{ masterId, address, name, port, crcCount, threshold }CRC errors crossed threshold
SyncUnitFault{ masterId, syncUnitId, hasError, faultCounter }Sync unit WC fault

Configuration

{
  "PlcTargets": {
    "Line1": {
      "AmsNetId": "192.168.1.136.1.1",
      "Port": 851,
      "EtherCat": {
        "PollingIntervalMs": 1000,
        "CrcErrorThreshold": 100,
        "EnableNotifications": true,
        "TimeoutMs": 5000
      }
    }
  }
}
FieldDescriptionDefault
PollingIntervalMsHow often to poll diagnostics data1000
CrcErrorThresholdCRC count that triggers notification100
EnableNotificationsEnable SignalR events for this PLCtrue
TimeoutMsADS read timeout for EtherCAT operations5000

ADS Implementation Notes

EtherCAT diagnostics are read via ADS from the EtherCAT master device:

  • Master NetId: derived from PLC NetId (byte 5 varies, e.g., .3.1)
  • Port 0xFFFF: all diagnostic reads target the master’s AMS NetId on port 65535
  • Per-slave reads: use the slave’s fixed address as the IO offset (not ADS port)
  • Connection: routes through the PLC’s TCP connection — no separate ADS route needed

Key ADS index groups on master port 0xFFFF:

IGIODescription
0x030x100Master state (uint16)
0x060x0Slave count (uint16)
0x070x0Slave address list (uint16[])
0x090x0All slave states (byte[] — 2 per slave)
0x09slave addrPer-slave state + link
0x0C0x0Frame counters (5× uint32)
0x11slave addrSlave identity (4× uint32: vendor, product, revision, serial)
0x12slave addrCRC errors per port (4× uint32)