> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coreflux.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Allen-Bradley Route

> Connect to Rockwell Automation PLCs over EtherNet/IP with symbolic tag names, program scope, UDTs, arrays, and bidirectional writes.

## Connect to Rockwell PLCs by Tag Name

The `ALLEN_BRADLEY` route connects Coreflux to Rockwell Automation PLCs using **symbolic tag names** over EtherNet/IP. Define an `ALLEN_BRADLEY_CONFIG` block, add TAGs with PLC tag addresses, and publish each data point to its own MQTT topic — with optional scaling, units, deadband, and bidirectional writes.

> [!TIP]
>
> **Like reading labels on a control panel.** Instead of numeric register addresses, you use the same tag names you see in Studio 5000 — `MainCounter`, `Program:MainProgram.Temperature`, `Motor1.Speed`.

> [!NOTE]
>
> For **explicit CIP paths** (`4.100.3.0`), use the [EtherNet/IP route](./ethernetip) instead. This route is for symbolic tag-name access; EtherNet/IP is for Class/Instance/Attribute addressing.

### Route and config aliases

| Alias | Canonical form |
| - | - |
| `TYPE AB` or `TYPE ALLENBRADLEY` | `TYPE ALLEN_BRADLEY` |
| `ADD AB_CONFIG` | `ADD ALLEN_BRADLEY_CONFIG` |

### Key capabilities

* **Symbolic tag names** — controller-scoped, program-scoped, UDT members, and arrays
* **Multiple PLC families** — ControlLogix, CompactLogix, Micro800, MicroLogix, PLC5, SLC500
* **TAG-based polling** — per-point MQTT topics with configurable intervals
* **Bidirectional writes** — `WRITABLE` tags with `DESTINATION_TOPIC`
* **Engineering units** — `SCALING`, `OFFSET`, `UNIT`, `DECIMAL_PLACES`, min/max clamping
* **Publish modes** — `VALUE_ONLY` (default) or `JSON` with quality metadata

***

## Quick Start

**Poll a controller tag**

Read a controller-scoped DINT counter every second:

```lot wrap focus={9-13} theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE ControlLogixPLC WITH TYPE ALLEN_BRADLEY
    ADD ALLEN_BRADLEY_CONFIG
        WITH IP "192.168.1.10"
        WITH DEVICE_FAMILY 0
        WITH PATH "1,0"
    ADD MAPPING ProductionData
        WITH EVERY 1 SECOND
        ADD TAG ProductCounter
            WITH ADDRESS "MainCounter"
            WITH DATA_TYPE "DINT"
            WITH SOURCE_TOPIC "production/counter"
```

**Program-scoped tags**

Read tags inside a specific program with units and deadband:

```lot wrap focus={9-16} theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE ControlLogix WITH TYPE ALLEN_BRADLEY
    ADD ALLEN_BRADLEY_CONFIG
        WITH IP "192.168.1.20"
        WITH DEVICE_FAMILY 0
    ADD MAPPING ProcessControl
        WITH EVERY 500 MILLISECONDS
        ADD TAG ReactorTemp
            WITH ADDRESS "Program:MainProgram.Temperature"
            WITH DATA_TYPE "REAL"
            WITH UNIT "°C"
            WITH DECIMAL_PLACES 2
            WITH DEADBAND 0.5
            WITH SOURCE_TOPIC "process/reactor/temperature"
```

**Read and write**

Poll a setpoint and accept MQTT writes to update it:

```lot wrap focus={9-18} theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE TemperatureControl WITH TYPE ALLEN_BRADLEY
    ADD ALLEN_BRADLEY_CONFIG
        WITH IP "192.168.1.60"
        WITH DEVICE_FAMILY 0
    ADD MAPPING ControlLoop
        WITH EVERY 1 SECOND
        ADD TAG TempSetpoint
            WITH ADDRESS "TempSetpoint"
            WITH DATA_TYPE "REAL"
            WITH UNIT "°C"
            WITH MIN_VALUE 0.0
            WITH MAX_VALUE 100.0
            WITH SOURCE_TOPIC "control/temperature/setpoint"
            WITH WRITABLE "true"
            WITH DESTINATION_TOPIC "control/temperature/setpoint/write"
```

**Micro800**

Read built-in I/O on a Micro800 controller:

```lot wrap focus={9-14} theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE Micro800PLC WITH TYPE ALLEN_BRADLEY
    ADD ALLEN_BRADLEY_CONFIG
        WITH IP "192.168.1.70"
        WITH DEVICE_FAMILY 4
    ADD MAPPING Micro800Data
        WITH EVERY 1 SECOND
        ADD TAG DigitalIn
            WITH ADDRESS "_IO_EM_DI_00"
            WITH DATA_TYPE "BOOL"
            WITH SOURCE_TOPIC "micro800/input0"
```

***

## Connection Configuration

### ALLEN\_BRADLEY\_CONFIG Parameters

| Parameter | Required | Default | Description |
| - | - | - | - |
| `IP` | Yes | — | PLC IP address |
| `DEVICE_FAMILY` | No | `0` | Device family code (0–6, see table below) |
| `PORT` | No | `44818` | EtherNet/IP port. Only honored for **Micro800** (`DEVICE_FAMILY 4`), which connects at `IP:PORT` — other families always use the default EtherNet/IP port. |
| `SLOT` | No | `0` | Parsed for legacy parity only. Backplane routing uses **`PATH`, not `SLOT`** — set the CPU slot in `PATH` (for example `"1,0"`). |
| `PATH` | No | `"1,0"` | Routing path to the PLC (format: `backplane,slot`). |
| `TIMEOUT` | No | `5000` | Per-tag read/write timeout in milliseconds |

> [!NOTE]
>
> The config block may be declared as `ADD ALLEN_BRADLEY_CONFIG` or `ADD AB_CONFIG` — both are equivalent.

> [!NOTE]
>
> Loading the route marks it ready; a transport is opened per tag read/write. `-checkRouteConnection` confirms the route is loaded but **does not probe the PLC** — verify connectivity with polling or a test read.

### Device Family Codes

| Code | Family | Use when |
| - | - | - |
| `0` | ControlLogix / CompactLogix | 1756-L6x, L7x, L8x, 1769-Lxx (most common) |
| `1` | PLC5 | 1785-L series (legacy) |
| `2` | SLC500 | 1747-L series (legacy) |
| `3` | ControlLogix PLC5 | Mixed environment |
| `4` | Micro800 | 2080-LC series |
| `5` | MicroLogix | 1766, 1764 series |
| `6` | Omron | NJ/NX with CIP support |

### Connection Examples

**ControlLogix / CompactLogix**

Standard backplane path to CPU in slot 0:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD ALLEN_BRADLEY_CONFIG
    WITH IP "192.168.1.100"
    WITH DEVICE_FAMILY 0
    WITH PATH "1,0"
    WITH TIMEOUT 5000
```

**MicroLogix**

MicroLogix 1100/1400:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD ALLEN_BRADLEY_CONFIG
    WITH IP "192.168.1.50"
    WITH DEVICE_FAMILY 5
    WITH TIMEOUT 5000
```

**Through backplane**

CPU in slot 2 on backplane 1:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD ALLEN_BRADLEY_CONFIG
    WITH IP "192.168.1.100"
    WITH DEVICE_FAMILY 0
    WITH PATH "1,2"
    WITH TIMEOUT 5000
```

**Micro800**

Micro800 — `PATH` is usually omitted:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD ALLEN_BRADLEY_CONFIG
    WITH IP "192.168.1.70"
    WITH DEVICE_FAMILY 4
    WITH TIMEOUT 5000
```

***

## Tag Addressing

Allen-Bradley PLCs use **tag-based addressing** (not register numbers). Tag names are case-sensitive.

| Scope | Format | Example |
| - | - | - |
| Controller | `TagName` | `MainCounter` |
| Program | `Program:ProgramName.TagName` | `Program:MainProgram.Counter` |
| Array element | `TagName[index]` | `Temps[5]` |
| UDT member | `UDTInstance.Member` | `Valve1.Status` |
| Nested UDT | `Parent.Child.GrandChild` | `Tank1.Level.Current` |
| I/O tags | `Local:Slot:Type.Data[index]` | `Local:1:I.Data[0]` |

### Tag naming rules

* Letters, numbers, and underscore only
* Must start with a letter or underscore
* Case-sensitive
* No spaces

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
# Valid
WITH ADDRESS "MainCounter"
WITH ADDRESS "Program:MainProgram.Temperature"
WITH ADDRESS "Valve1.Status"
WITH ADDRESS "Temps[5]"
```

***

## Data Types

| Coreflux `DATA_TYPE` | AB type | Notes |
| - | - | - |
| `BOOL` | BOOL | Boolean |
| `SINT` | SINT | Signed 8-bit |
| `USINT` / `BYTE` | USINT | Unsigned 8-bit |
| `INT` | INT | Signed 16-bit |
| `UINT` / `WORD` | UINT | Unsigned 16-bit |
| `DINT` | DINT | Signed 32-bit |
| `UDINT` / `DWORD` | UDINT | Unsigned 32-bit |
| `LINT` | LINT | Signed 64-bit |
| `ULINT` / `LWORD` | ULINT | Unsigned 64-bit |
| `REAL` / `FLOAT` | REAL | 32-bit float |
| `LREAL` / `DOUBLE` | LREAL | 64-bit float — MQTT values round to `DECIMAL_PLACES` (default `2`) |
| `CHAR` | CHAR | Single character |
| `WCHAR` | WCHAR | Wide character |
| `STRING` | STRING | Fixed 88-byte CIP layout — see encoding notes below |
| `TIME` | TIME | Duration in ms — published as `T#XdXhXmXsXms` |
| `DATE` | DATE | Date value |
| `TOD` | TOD | Time of day |

### STRING encoding

The route uses a **fixed 88-byte** CIP `STRING` layout. Neither `LENGTH` nor `STRING_SIZE` resizes this layout — `STRING_SIZE` is accepted as an alias for the same field and has the same limitation.

Encoding still depends on `DEVICE_FAMILY`:

* **ControlLogix / CompactLogix (default):** 4-byte DINT length prefix + up to 82 ASCII characters
* **Micro800:** 1-byte length prefix + characters

### TIME encoding

Raw value is a signed 32-bit millisecond count. MQTT publishes Allen-Bradley-style duration strings (for example `T#1h1m1s1ms`).

***

## TAG Configuration

Every polled data point is an `ADD TAG` inside an `ADD MAPPING` block.

### Complete TAG Example

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD TAG MotorSpeed
    WITH ADDRESS "Motor1.ActualSpeed"
    WITH ADDRESS_TYPE "SYMBOL"
    WITH DATA_TYPE "REAL"
    WITH SOURCE_TOPIC "plc/motor1/speed"
    WITH SCALING 1
    WITH OFFSET 0
    WITH UNIT "RPM"
    WITH DECIMAL_PLACES 2
    WITH MIN_VALUE 0
    WITH MAX_VALUE 3600
    WITH DEADBAND 10
    WITH PUBLISH_MODE "JSON"
    WITH DESCRIPTION "Motor 1 actual speed in RPM"
```

### TAG Parameters

> **Address and data type**
>
> **ADDRESS** `string` *required*
>
> PLC tag name — controller-scoped (`MainCounter`), program-scoped (`Program:MainProgram.Counter`), UDT member (`Valve1.Status`), or array (`Temps[0]`).
>
> **ADDRESS\_TYPE** `string`
>
> `SYMBOL` (default) or `PATH`.
>
> **DATA\_TYPE** `string` *required*
>
> Logix data type: `BOOL`, `SINT`, `INT`, `DINT`, `LINT`, `USINT`, `UINT`, `UDINT`, `ULINT`, `REAL`, `LREAL`, `STRING`, `TIME`, etc.

> **Value transformation**
>
> **SCALING** `decimal`
>
> Multiply the parsed value after read. Alias: `SCALING_FACTOR`. Default: `1.0`.
>
> **OFFSET** `decimal`
>
> Add after scaling. Default: `0.0`.
>
> **UNIT** `string`
>
> Engineering unit (for example `°C`, `bar`, `RPM`). Included in JSON publish mode.
>
> **DECIMAL\_PLACES** `integer`
>
> Rounding precision for float MQTT payloads. Default: `2`.

> **Filtering**
>
> **MIN\_VALUE** `double`
>
> Clamp minimum allowed value (especially for writable tags).
>
> **MAX\_VALUE** `double`
>
> Clamp maximum allowed value.
>
> **DEADBAND** `double`
>
> Suppress MQTT publish when the change is below this threshold. Default: `0.0`.

> **Publishing and writes**
>
> **SOURCE\_TOPIC** `string` *required*
>
> MQTT topic where polled values are published.
>
> **PUBLISH\_MODE** `string`
>
> `VALUE_ONLY` (default) or `JSON` (value, unit, quality, timestamp, description).
>
> **WRITABLE** `boolean`
>
> When `"true"`, subscribe to `DESTINATION_TOPIC` and write incoming MQTT values to the PLC.
>
> **DESTINATION\_TOPIC** `string`
>
> MQTT topic to receive write commands. Required when `WRITABLE` is `"true"`.
>
> **DESCRIPTION** `string`
>
> Human-readable description (included in JSON publish mode).

### Publish Modes

**VALUE\_ONLY** (default) — publishes just the scaled value:

```
12345
```

**JSON** — metadata wrapper when explicitly set:

```json wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "tag_name": "SafetyPressure",
  "value": 8.456,
  "unit": "bar",
  "quality": "GOOD",
  "timestamp": "2025-12-17T10:30:45.123Z",
  "description": "Critical safety pressure sensor"
}
```

***

## Event-Based Operations

For on-demand tag reads and writes (not continuous polling), add an `ADD EVENT` block. Publish any message to `SOURCE_TOPIC` to trigger the operation; results appear on `DESTINATION_TOPIC`.

### Query Parameters

| Parameter | Description | Example |
| - | - | - |
| `operation` | `READ` or `WRITE` | `READ` |
| `variable` | PLC tag name | `Program:MainProgram.Counter`, `MainCounter` |
| `data_type` | Logix data type | `DINT`, `REAL`, `BOOL` |
| `value` | Value to write (WRITE only) | `42`, `75.0` |

### Read Example

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD EVENT ReadOnDemand
    WITH SOURCE_TOPIC "ab/commands/read"
    WITH DESTINATION_TOPIC "ab/responses/read"
    WITH QUERY "{operation: READ, variable: Program:MainProgram.Counter, data_type: DINT}"
```

### Write Example

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD EVENT WriteSetpoint
    WITH SOURCE_TOPIC "ab/commands/write"
    WITH DESTINATION_TOPIC "ab/responses/write"
    WITH QUERY "{operation: WRITE, variable: TIC100.SP, data_type: REAL, value: 150.0}"
```

***

## Examples

**Multiple data types**

Monitor BOOL, DINT, and REAL tags in one mapping:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE ProductionLine WITH TYPE ALLEN_BRADLEY
    ADD ALLEN_BRADLEY_CONFIG
        WITH IP "192.168.1.30"
        WITH DEVICE_FAMILY 0
    ADD MAPPING MachineMonitor
        WITH EVERY 1 SECOND
        ADD TAG MachineRunning
            WITH ADDRESS "MachineStatus.Running"
            WITH DATA_TYPE "BOOL"
            WITH SOURCE_TOPIC "machine/status/running"
        ADD TAG ProductCount
            WITH ADDRESS "ProductionCounters.TotalCount"
            WITH DATA_TYPE "DINT"
            WITH SOURCE_TOPIC "machine/production/total"
        ADD TAG LineSpeed
            WITH ADDRESS "LineSpeed"
            WITH DATA_TYPE "REAL"
            WITH UNIT "units/min"
            WITH SOURCE_TOPIC "machine/speed"
```

**UDT members**

Read User-Defined Type structure members:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE UDTAccess WITH TYPE ALLEN_BRADLEY
    ADD ALLEN_BRADLEY_CONFIG
        WITH IP "192.168.1.40"
        WITH DEVICE_FAMILY 0
    ADD MAPPING ValveControl
        WITH EVERY 500 MILLISECONDS
        ADD TAG Valve1Position
            WITH ADDRESS "Valve1.Position"
            WITH DATA_TYPE "INT"
            WITH UNIT "%"
            WITH SOURCE_TOPIC "valves/valve1/position"
        ADD TAG Valve1Status
            WITH ADDRESS "Valve1.Status"
            WITH DATA_TYPE "BOOL"
            WITH SOURCE_TOPIC "valves/valve1/status"
```

**Array elements**

Read specific array indices:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE ArrayData WITH TYPE ALLEN_BRADLEY
    ADD ALLEN_BRADLEY_CONFIG
        WITH IP "192.168.1.50"
        WITH DEVICE_FAMILY 0
    ADD MAPPING ArrayMonitor
        WITH EVERY 1 SECOND
        ADD TAG Zone1Temp
            WITH ADDRESS "ZoneTemperatures[0]"
            WITH DATA_TYPE "REAL"
            WITH UNIT "°C"
            WITH SOURCE_TOPIC "zones/zone1/temperature"
        ADD TAG Zone2Temp
            WITH ADDRESS "ZoneTemperatures[1]"
            WITH DATA_TYPE "REAL"
            WITH UNIT "°C"
            WITH SOURCE_TOPIC "zones/zone2/temperature"
```

**Control loop**

Read process value and write setpoint from MQTT:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE ControlLoop WITH TYPE ALLEN_BRADLEY
    ADD ALLEN_BRADLEY_CONFIG
        WITH IP "192.168.1.100"
        WITH DEVICE_FAMILY 0
    ADD MAPPING TempControl
        WITH EVERY 200 MILLISECONDS
        ADD TAG PV
            WITH ADDRESS "TIC100.PV"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "control/tic100/pv"
            WITH UNIT "°F"
        ADD TAG SP
            WITH ADDRESS "TIC100.SP"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "control/tic100/sp"
            WITH UNIT "°F"
            WITH WRITABLE "true"
            WITH DESTINATION_TOPIC "control/tic100/sp/set"
            WITH MIN_VALUE 32
            WITH MAX_VALUE 212
```

**Scaled analog**

Scale a 4–20 mA sensor to engineering units:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE AnalogSensors WITH TYPE ALLEN_BRADLEY
    ADD ALLEN_BRADLEY_CONFIG
        WITH IP "192.168.1.80"
        WITH DEVICE_FAMILY 0
    ADD MAPPING AnalogData
        WITH EVERY 500 MILLISECONDS
        ADD TAG Pressure
            WITH ADDRESS "AI_Pressure"
            WITH DATA_TYPE "REAL"
            WITH UNIT "bar"
            WITH DECIMAL_PLACES 3
            WITH DEADBAND 0.01
            WITH SOURCE_TOPIC "sensors/pressure"
```

***

## Best Practices

> **Choose the correct device family**
>
> Use `DEVICE_FAMILY 0` for ControlLogix and CompactLogix (most common), `4` for Micro800, and `5` for MicroLogix. Legacy PLC5/SLC500 families (`1`/`2`) only for existing installations.

> **Program scope**
>
> Controller-scoped tags use the name alone (`GlobalCounter`). Program-scoped tags need the full prefix: `Program:MainProgram.LocalCounter`.

> **PATH vs SLOT**
>
> Set the CPU slot in `PATH` (`"1,0"` for backplane 1, slot 0). `SLOT` is kept for legacy parity, but routing is always resolved from `PATH`.

> **Writable tags**
>
> Use `WRITABLE "true"` with `MIN_VALUE` / `MAX_VALUE` on setpoints. Ensure the PLC is in Remote Run mode for writes to succeed.

> **Deadbands and polling**
>
> Use `DEADBAND` on noisy analog values. Match `EVERY` to how fast the value changes — 500 ms for critical data, 1–5 s for slow status.

***

## Troubleshooting

> **Connection failed**
>
> * Verify IP with `ping`
> * Confirm port 44818 is open
> * Ensure PLC is powered on and in **RUN** mode
> * Check `DEVICE_FAMILY` matches your controller type
> * Increase `TIMEOUT` on slow networks
> * Remember: `-checkRouteConnection` does not probe the PLC — use a polling TAG to verify

> **Tag not found**
>
> * Tag names are **case-sensitive** — match Studio 5000 exactly
> * Program-scoped tags need `Program:ProgramName.TagName` (not `ProgramName:Tag`)
> * Verify the tag exists in Controller Tags or Program Tags in Studio 5000
> * For UDTs, include the member: `Valve1.Status` not `Valve1`
> * For arrays, include the index: `Temps[0]` not `Temps`

> **Path errors**
>
> * Use `PATH "1,0"` for standard backplane routing (backplane, slot)
> * For Micro800, omit `PATH` or leave it unset
> * Multi-hop paths use comma-separated segments: `"1,2,2,1"` through bridge modules

> **Micro800 issues**
>
> * Set `DEVICE_FAMILY 4`
> * Use Micro800 I/O tag names (`_IO_EM_DI_00`, `_IO_EM_AI_00`)
> * STRING uses 1-byte length prefix (not ControlLogix 4-byte format)

> **Write operations fail**
>
> * Set `WRITABLE "true"` and provide `DESTINATION_TOPIC`
> * PLC must be in **Remote Run** mode
> * Verify `DATA_TYPE` matches the PLC tag definition
> * Check value is within `MIN_VALUE` / `MAX_VALUE` if set

> **Data type mismatch**
>
> * Match PLC types exactly: DINT → `DINT`, REAL → `REAL`, BOOL → `BOOL`
> * `TIME` tags publish as `T#...` duration strings on MQTT

***

## Next Steps

> **[EtherNet/IP Route](./ethernetip)**
>
> Explicit CIP Class/Instance/Attribute addressing for assembly objects and legacy devices.

> **[Industrial Routes Overview](./overview)**
>
> Compare OT routes and choose the right protocol for your devices.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.