# Allen-Bradley EtherNet/IP
Talks **CIP over EtherNet/IP** to Rockwell **ControlLogix** and **CompactLogix**
controllers. Tags are addressed by name — controller tags as well as program tags —
and the running tag directory can be browsed to pick addresses.
| | |
|---|---|
| Connection string | `ethernet.ip://HOST[/SLOT]` (port fixed to `44818` by the protocol) |
| Reads | ✔ (poll) |
| Writes | ✔ |
| Subscriptions | — |
| Browsing | ✔ (tag directory) |
## Device options
| Key | Type | Default | Meaning |
|---|---|---|---|
| `slot` | int | `0` | Slot of the controller on the backplane. Only used when the connection string does not carry a `/SLOT` segment. |
## Address format
```
TAGNAME[::ELEMENTCOUNT]
```
- `TAGNAME` — a controller or program tag: `MyTag`, `Program:Main.MyTag`,
`MyStruct.Member`, `MyArray[3]`.
- `ELEMENTCOUNT > 1` reads an array tag and expands it into one dimension per
element (labelled `label[0]`, `label[1]`, …).
Scalar tags are batched into one CIP multi-request transaction per poll cycle; array
tags are read individually. The value type follows the CIP type of the tag: `BOOL`
→ Boolean, strings → String, all numeric types → Number.
## Example configuration
```json
{
"devices": [
{
"objectId": "clx1",
"name": "Line 3 PLC",
"connectionString": "ethernet.ip://10.0.0.20/0",
"interval": 1000,
"enabled": true,
"options": {},
"extraOptions": { "host": "broker:1883", "clientId": "openconnect" }
}
],
"items": [
{
"objectId": "count",
"DeviceID": { "objectId": "clx1" },
"address": "Program:Main.PartCounter",
"label": "Part counter",
"type": "Number",
"unit": "#",
"source": { "tag": "line3" },
"enabled": true,
"onChange": true,
"extraOptions": {}
},
{
"objectId": "temps",
"DeviceID": { "objectId": "clx1" },
"address": "ZoneTemps::4",
"label": "Zone temperature",
"type": "Number",
"unit": "°C",
"source": { "tag": "line3" },
"enabled": true,
"onChange": false,
"extraOptions": {}
}
]
}
```
## Writes
The write topic is the tag name; the payload is the value. The tag is read first to
determine its CIP type; `true`/`false` payloads are mapped to `1`/`0` for
numeric/BOOL tags.
```bash
# HTTP
curl -X POST "http://openconnect:8080/write/clx1/Program:Main.SetPoint" \
-H "Authorization: Bearer $TOKEN" -d '42.5'
# MQTT — tag names contain dots, so use the topic-in-payload form with RabbitMQ
mosquitto_pub -t 'write/clx1' \
-m '{"topic": "Program:Main.SetPoint", "payload": "42.5"}'
```
See the [write API](../write-api.md) for authentication and why the JSON form
matters with RabbitMQ.
## Tag browsing
`GET /tags?connectorId=<device objectId>` (capability `api`) enumerates the tag
directory of a running connector — one entry per tag with `tag`, `type`,
`dimensions`, and `instanceId`; `tag` is directly usable as item `address`. Program
tags are included as `Program:Name.Tag` unless `programTags=false` is passed. The
same browser is available in the [management UI](../management-ui.md).
## Testing without hardware
A ControlLogix emulator (cpppo-based) is available in the
`openinc-openconnect-docker` repo under `test-devices/ethernetip` with a matching
device config in the instance repo. It covers reads (including arrays and batching)
and writes; tag browsing needs Studio 5000 Logix Echo or a real controller.