com.mbreissi.edgecommons.EthernetIpAdapter is the Rust reference southbound EtherNet/IP adapter
for the EdgeCommons ecosystem. It connects to EtherNet/IP devices — Allen-Bradley
ControlLogix/CompactLogix PLCs and generic CIP endpoints — and bridges their data onto the Unified
Namespace as normalized SouthboundSignalUpdate messages, so a consumer can chart an EtherNet/IP signal
next to a Modbus register or an OPC UA node without knowing the protocol.
It is built on the edgecommons Rust library and an owned pure-Rust EtherNet/IP + CIP stack (the enip
crate), and runs on all three platforms — Greengrass v2, HOST (standalone process/container), and
Kubernetes.
Each configured device runs in one of EtherNet/IP's two native data models:
- Poll (default) — scheduled explicit-messaging reads of CIP tags, grouped by cadence into
pollGroups[]. This is the model for ControlLogix/CompactLogix tags. - Push — class-1 implicit I/O: the device produces an assembly at the RPI and the adapter maps
its byte-offset fields to signals (
ioblock). This is the model for remote-I/O adapters and drives.
Either mode publishes value changes on the data class, emits southbound_health plus operational
metrics, and serves a command surface: nine sb/*/reconnect/repoll verbs including on-demand read,
allow-listed write, tag browse, and per-instance pause/resume. Writes are allow-listed and empty by
default — every device is read-only until you list the signal ids it may write, and the allow-list is
checked before any device I/O.
Run against the built-in hardware-free simulator (no PLC needed), publishing to a local MQTT broker:
docker run -d -p 1883:1883 emqx/emqx # a local broker
cargo run -p ethernet-ip-adapter -- \
--platform HOST --transport MQTT ./crates/ethernet-ip-adapter/test-configs/standalone-messaging.json \
-c FILE ./crates/ethernet-ip-adapter/test-configs/config.json \
-t my-thingWatch the values flow (one wildcard covers the fleet):
mosquitto_sub -t 'ecv1/+/+/+/data/#' -vThe bundled compose.yaml also brings up a cpppo tag server (live
poll target) and an OpENer I/O adapter (live class-1 push
target) — see the tutorial.
| Flag | Values |
|---|---|
--platform |
GREENGRASS | HOST | KUBERNETES | auto (default) |
--transport |
MQTT [messaging.json] | IPC (Greengrass-only) |
-c/--config |
FILE <path> | GG_CONFIG | CONFIGMAP | … (default by platform) |
-t/--thing |
IoT Thing name — the {device} token of every UNS topic |
Full docs live under docs/ (synced to
docs.edgecommons.mbreissi.com):
| Doc | For |
|---|---|
| Tutorial | Bring the adapter up against a simulator, end to end. |
| How-to guides | Configure poll/push devices, allow-list writes, pause, browse, deploy. |
| Explanation | Poll vs push, the signal model, secure-by-default writes, the connection lifecycle. |
| Sample configurations | Annotated complete poll and push configs. |
| Reference — Configuration | Every config key, type, and default. |
| Reference — Messaging | Topics, the SouthboundSignalUpdate body, the nine verbs, error codes. |
| Reference — Metrics | Every metric family, measure, and dimension. |
| Reference — Data Types | The CIP types, arrays, scaling, and quality. |
- Value types: CIP elementary scalars (
bool,sint/usint/int/uint/dint/udint/lint/ulint,real,lreal) and 1-D arrays of 1–65535 elements thereof. Structures/UDTs, LogixSTRING, and multi-dimensional arrays are not supported. BOOL array signals are experimental: the adapter reads whichever representation the device declares — byte-per-element, or the packedDWORDs Logix controllers store BOOL arrays as, unpacked into the configured booleans — and refuses writes to a tag it has observed packed. - Poll uses CIP explicit messaging (one request per signal per cycle); push uses class-1 implicit I/O.
- Security: poll (explicit-messaging) instances can run over EtherNet/IP over TLS (CIP Security,
TCP
2221) with mutual X.509 authentication — configured per connection viaconnection.security(see the configuration reference). Plaintext (TCP44818) is the default. Only AEAD cipher suites are negotiated — TLS 1.3, and TLS 1.2 ECDHE with AES-GCM or ChaCha20-Poly1305; CBC, NULL, and PSK suites are not available. Class-1 implicit I/O (mode: push) runs over plaintext UDP2222; a push instance configured with TLS is rejected at startup. On plaintext instances the network segment is the protection — deploy on an isolated OT segment.
Business Source License 1.1 (BSL 1.1) — see LICENSE. You may use, copy, modify, and self-host the Licensed Work free of charge for development, testing, staging, evaluation, academic research, and personal/non-commercial use; production use in a commercial product or service requires a separate commercial license. Each released version converts to the Mozilla Public License 2.0 on its fourth anniversary. See the license file for the exact terms.