Skip to content

PLC Communication

Consystence edge devices communicate with PLCs over EtherNet/IP using the libplctag library (MPL 2.0 licence). The .NET NuGet package libplctag provides the managed wrapper.

Protocol overview

Aspect Detail
Protocol EtherNet/IP with CIP (Common Industrial Protocol)
Transport Direct TCP on port 44818
Encapsulation CIP over EtherNet/IP
.NET Library libplctag NuGet package
Licence MPL 2.0

Validated hardware

Primary testing is against Rockwell ControlLogix:

Controller Firmware Validated Operations
ControlLogix 1756-L82E/B V38.11 BOOL, SINT, REAL reads + writes

Performance benchmarks

Metric Result
Response time (12 tags) 7–15 ms
Stability 100+ consecutive poll cycles, zero errors
Poll interval 100 ms (configurable)

CIP tag paths

Tags are addressed using CIP tag paths. Controller-scope tags use the tag name directly — no Program: prefix is required:

EQ_PP427.STS.Running        # Status: pump running (BOOL)
EQ_PP427.STS.Speed           # Status: motor speed (REAL)
EQ_PP427.CMD.Start           # Command: start pulse (BOOL)
EQ_PP427.CMD.SpeedSP         # Command: speed setpoint (REAL)

Deftec UDT tag structure

Deftec's PLC libraries use a consistent UDT structure for all equipment. Tags are grouped by function:

EQ_PP427                     # Equipment instance (Pump 427)
├── STS                      # Status structure
│   ├── Running              # BOOL — pump is running
│   ├── Faulted              # BOOL — drive fault active
│   ├── Speed                # REAL — current speed (RPM)
│   ├── Current              # REAL — motor current (A)
│   ├── BrgTempDE            # REAL — DE bearing temp (°C)
│   ├── BrgTempNDE           # REAL — NDE bearing temp (°C)
│   ├── RunHours             # DINT — cumulative run hours
│   └── StartCount           # DINT — cumulative starts
├── CMD                      # Command structure
│   ├── Start                # BOOL — start pulse
│   ├── Stop                 # BOOL — stop pulse
│   ├── Reset                # BOOL — fault reset pulse
│   └── SpeedSP              # REAL — speed setpoint (RPM)
└── CFG                      # Configuration structure
    ├── MaxSpeed             # REAL — max speed limit
    └── AlarmDelays          # DINT — alarm delay (ms)

This structure maps directly to Consystence device type tags. The device instance mapping connects type tag names to CIP paths.

CIP path configuration

The CIP path identifies the route to the PLC through the network:

{
  "Gateway": "192.168.1.1",
  "Path": "1,0",
  "Protocol": "ab_eip"
}
Field Description
Gateway IP address of the PLC or Ethernet module
Path CIP routing path — "1,0" means backplane slot 0 (typical for ControlLogix)
Protocol "ab_eip" for Allen-Bradley EtherNet/IP

External access rules

PLC tag access is controlled by the Rockwell external access configuration:

Tag Group External Access Rationale
STS.* (status) Read Only Edge reads process values
CMD.* (commands) Read/Write Edge writes operator commands
CFG.* (config) Read Only Edge reads configuration

Warning

The PLC program is the authority over the physical process. The edge device reads status and writes commands — it never modifies configuration or safety-critical parameters directly.

Reading and writing tags

Reading

The edge service polls all mapped tags at the configured interval (default 100ms):

using libplctag;

var tag = new Tag
{
    Gateway = "192.168.1.1",
    Path = "1,0",
    Protocol = Protocol.ab_eip,
    Name = "EQ_PP427.STS.Speed",
    PlcType = PlcType.ControlLogix
};

await tag.ReadAsync();
float speed = tag.GetFloat32(0);

Writing

Commands are written as pulse values — set to true, hold for the pulse duration, then reset:

var tag = new Tag
{
    Gateway = "192.168.1.1",
    Path = "1,0",
    Protocol = Protocol.ab_eip,
    Name = "EQ_PP427.CMD.Start",
    PlcType = PlcType.ControlLogix
};

// Set command bit
tag.SetBit(0, true);
await tag.WriteAsync();

// Hold for pulse duration
await Task.Delay(500);

// Reset command bit
tag.SetBit(0, false);
await tag.WriteAsync();

In practice, this pulse logic is handled by the command execution pipeline in the EdgeDeviceGrain — operators never interact with raw tag writes.