> ## 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.

# EtherNet/IP Route

> Connect to Allen-Bradley PLCs and CIP-compatible devices using EtherNet/IP explicit messaging

## EtherNet/IP Overview

The `ETHERNETIP` route enables communication with CIP (Common Industrial Protocol) compatible devices using EtherNet/IP explicit messaging. It provides access to device attributes using CIP addressing (Class, Instance, Attribute) and supports Allen-Bradley PLCs and other EtherNet/IP devices.

<Tip>
  EtherNet/IP uses CIP addressing which provides structured access to device data. Use this route when you need explicit messaging to specific CIP objects.
</Tip>

## Basic Syntax

```lot theme={null}
DEFINE ROUTE EIPDevice WITH TYPE ETHERNETIP
    ADD ETHERNETIP_CONFIG
        WITH IP "192.168.1.100"
        WITH PORT 44818
        WITH POLLING_MS 750
    ADD MAPPING DeviceData
        WITH EVERY 1 SECOND
        ADD TAG Temperature
            WITH ADDRESS "1.1.100.0"
            WITH DATA_TYPE "FLOAT32"
            WITH SOURCE_TOPIC "eip/temperature"
```

***

## Connection Configuration

### ETHERNETIP\_CONFIG Parameters

<ParamField path="IP" type="string" required>
  EtherNet/IP device IP address.
</ParamField>

<ParamField path="PORT" type="integer">
  EtherNet/IP port. Default: 44818.
</ParamField>

<ParamField path="POLLING_MS" type="integer">
  Polling interval in milliseconds. Default: 750.
</ParamField>

<ParamField path="CONNECTION_TIMEOUT" type="integer">
  Connection timeout in milliseconds. Default: 5000.
</ParamField>

<ParamField path="READ_WRITE_TIMEOUT" type="integer">
  Read/Write timeout in milliseconds. Default: 3000.
</ParamField>

<ParamField path="RETRY_ATTEMPTS" type="integer">
  Number of retry attempts. Default: 3.
</ParamField>

<ParamField path="RETRY_TIME_SECONDS" type="integer">
  Retry delay in seconds. Default: 5.
</ParamField>

### Connection Example

```lot theme={null}
ADD ETHERNETIP_CONFIG
    WITH IP "192.168.1.100"
    WITH PORT 44818
    WITH POLLING_MS 500
    WITH CONNECTION_TIMEOUT 5000
    WITH READ_WRITE_TIMEOUT 3000
    WITH RETRY_ATTEMPTS 3
    WITH RETRY_TIME_SECONDS 5
```

***

## CIP Addressing

EtherNet/IP uses CIP addressing in the format: `ClassID.InstanceID.AttributeID.AttributeIndex`

| Component      | Description      | Example                          |
| -------------- | ---------------- | -------------------------------- |
| ClassID        | CIP object class | 1 (Identity), 4 (Assembly), etc. |
| InstanceID     | Object instance  | 1, 2, 3...                       |
| AttributeID    | Attribute number | Varies by class                  |
| AttributeIndex | Index for arrays | 0 for first element              |

### Common CIP Classes

| Class ID | Name                  | Description           |
| -------- | --------------------- | --------------------- |
| 1        | Identity              | Device identification |
| 2        | Message Router        | Message routing       |
| 4        | Assembly              | I/O assemblies        |
| 6        | Connection Manager    | Connection handling   |
| 102      | Analog Input Point    | Analog inputs         |
| 103      | Analog Output Point   | Analog outputs        |
| 104      | Discrete Input Point  | Digital inputs        |
| 105      | Discrete Output Point | Digital outputs       |

***

## Data Types

<ParamField path="DATA_TYPE" type="string" required>
  CIP data type for the attribute:
</ParamField>

| Data Type                      | Description                          | Size     |
| ------------------------------ | ------------------------------------ | -------- |
| `BOOLEAN` / `BOOL`             | Boolean value                        | 1 bit    |
| `BYTE`                         | Unsigned 8-bit                       | 8 bits   |
| `USINT`                        | Unsigned 8-bit integer               | 8 bits   |
| `SINT`                         | Signed 8-bit integer                 | 8 bits   |
| `INT16` / `INT`                | Signed 16-bit integer                | 16 bits  |
| `UINT16` / `UINT` / `WORD`     | Unsigned 16-bit integer              | 16 bits  |
| `INT32` / `DINT`               | Signed 32-bit integer                | 32 bits  |
| `UINT32` / `UDINT` / `DWORD`   | Unsigned 32-bit integer              | 32 bits  |
| `INT64` / `LINT`               | Signed 64-bit integer                | 64 bits  |
| `UINT64` / `ULINT` / `LWORD`   | Unsigned 64-bit integer              | 64 bits  |
| `FLOAT32` / `REAL` / `FLOAT`   | 32-bit floating point                | 32 bits  |
| `FLOAT64` / `LREAL` / `DOUBLE` | 64-bit floating point                | 64 bits  |
| `CHAR`                         | Single character                     | 8 bits   |
| `WCHAR`                        | Wide character                       | 16 bits  |
| `TIME`                         | Time duration                        | 32 bits  |
| `DATE`                         | Date value                           | 16 bits  |
| `TOD`                          | Time of day                          | 32 bits  |
| `ASCII`                        | ASCII string                         | 8 bits   |
| `STRING`                       | String value (configurable `LENGTH`) | Variable |

***

## TAG Configuration

### Complete TAG Example

```lot theme={null}
ADD TAG ProcessTemperature
    WITH ADDRESS "102.1.3.0"
    WITH DATA_TYPE "FLOAT32"
    WITH SOURCE_TOPIC "eip/process/temperature"
    WITH SCALING_FACTOR 0.1
    WITH OFFSET 0
    WITH DEADBAND 0.5
    WITH PUBLISH_MODE "JSON"
    WITH LENGTH 1
```

### TAG Parameters

<AccordionGroup>
  <Accordion title="Address Configuration">
    <ParamField path="ADDRESS" type="string" required>
      CIP address in format: ClassID.InstanceID.AttributeID.AttributeIndex
    </ParamField>

    <ParamField path="DATA_TYPE" type="string" required>
      CIP data type: BOOLEAN, BYTE, INT16, UINT16, INT32, UINT32, INT64, UINT64, FLOAT32, FLOAT64, ASCII, STRING.
    </ParamField>

    <ParamField path="LENGTH" type="integer">
      String length (for STRING type only).
    </ParamField>
  </Accordion>

  <Accordion title="Value Transformation">
    <ParamField path="SCALING_FACTOR" type="decimal">
      Scaling multiplier for the value.
    </ParamField>

    <ParamField path="OFFSET" type="decimal">
      Value offset applied after scaling.
    </ParamField>

    <ParamField path="DEADBAND" type="decimal">
      Suppress updates if change is less than threshold.
    </ParamField>
  </Accordion>

  <Accordion title="Publishing">
    <ParamField path="SOURCE_TOPIC" type="string">
      Topic where PLC values are published. Subscribe here to receive sensor data.
    </ParamField>

    <ParamField path="PUBLISH_MODE" type="string">
      Output format: `JSON`, `RAW`, or `BINARY`. Default: JSON.
    </ParamField>
  </Accordion>
</AccordionGroup>

***

## Event-Based Operations

For on-demand EtherNet/IP operations (not polling), use the EVENT syntax. Publish a message to SOURCE\_TOPIC to trigger the operation; the route executes it and publishes the result to DESTINATION\_TOPIC.

### Supported Operations

| Operation | Description                      | Query Parameters                |
| --------- | -------------------------------- | ------------------------------- |
| `READ`    | Read a CIP attribute on demand   | `address`, `data_type`          |
| `WRITE`   | Write a value to a CIP attribute | `address`, `data_type`, `value` |

### Query Parameters

| Parameter   | Description                                       | Example                                  |
| ----------- | ------------------------------------------------- | ---------------------------------------- |
| `operation` | Operation type: `READ` or `WRITE`                 | `READ`                                   |
| `address`   | CIP address: ClassID.InstanceID.AttributeID.Index | `102.1.3.0`, `1.1.7.0`                   |
| `data_type` | CIP data type                                     | `FLOAT32`, `UINT16`, `BOOLEAN`, `STRING` |
| `value`     | Value to write (WRITE only)                       | `50.0`, `1`, `true`                      |

### Read Example

Read an analog input point value on demand:

```lot theme={null}
ADD EVENT ReadAttribute
    WITH SOURCE_TOPIC "eip/commands/read"
    WITH DESTINATION_TOPIC "eip/responses/read"
    WITH QUERY "{operation: READ, address: 102.1.3.0, data_type: FLOAT32}"
```

### Write Example

Write to an analog output point on demand:

```lot theme={null}
ADD EVENT WriteOutput
    WITH SOURCE_TOPIC "eip/commands/write"
    WITH DESTINATION_TOPIC "eip/responses/write"
    WITH QUERY "{operation: WRITE, address: 103.1.3.0, data_type: FLOAT32, value: 50.0}"
```

***

## Complete Examples

<Tabs>
  <Tab title="Device Identity">
    Read device identity information:

    ```lot theme={null}
    DEFINE ROUTE DeviceIdentity WITH TYPE ETHERNETIP
        ADD ETHERNETIP_CONFIG
            WITH IP "192.168.1.100"
            WITH PORT 44818
            WITH POLLING_MS 5000
        ADD MAPPING IdentityData
            WITH EVERY 30 SECONDS
            ADD TAG VendorID
                WITH ADDRESS "1.1.1.0"
                WITH DATA_TYPE "UINT16"
                WITH SOURCE_TOPIC "device/identity/vendor"
            ADD TAG DeviceType
                WITH ADDRESS "1.1.2.0"
                WITH DATA_TYPE "UINT16"
                WITH SOURCE_TOPIC "device/identity/type"
            ADD TAG ProductCode
                WITH ADDRESS "1.1.3.0"
                WITH DATA_TYPE "UINT16"
                WITH SOURCE_TOPIC "device/identity/product"
            ADD TAG SerialNumber
                WITH ADDRESS "1.1.6.0"
                WITH DATA_TYPE "UINT32"
                WITH SOURCE_TOPIC "device/identity/serial"
            ADD TAG ProductName
                WITH ADDRESS "1.1.7.0"
                WITH DATA_TYPE "STRING"
                WITH LENGTH 32
                WITH SOURCE_TOPIC "device/identity/name"
    ```
  </Tab>

  <Tab title="Analog I/O">
    Read analog input points:

    ```lot theme={null}
    DEFINE ROUTE AnalogIO WITH TYPE ETHERNETIP
        ADD ETHERNETIP_CONFIG
            WITH IP "192.168.1.100"
            WITH PORT 44818
            WITH POLLING_MS 500
        ADD MAPPING AnalogInputs
            WITH EVERY 500 MILLISECONDS
            ADD TAG AnalogIn1
                WITH ADDRESS "102.1.3.0"
                WITH DATA_TYPE "FLOAT32"
                WITH SOURCE_TOPIC "io/analog/in/1"
                WITH SCALING_FACTOR 0.01
                WITH OFFSET 0
                WITH DEADBAND 0.1
            ADD TAG AnalogIn2
                WITH ADDRESS "102.2.3.0"
                WITH DATA_TYPE "FLOAT32"
                WITH SOURCE_TOPIC "io/analog/in/2"
                WITH SCALING_FACTOR 0.01
                WITH DEADBAND 0.1
            ADD TAG AnalogIn3
                WITH ADDRESS "102.3.3.0"
                WITH DATA_TYPE "FLOAT32"
                WITH SOURCE_TOPIC "io/analog/in/3"
                WITH SCALING_FACTOR 0.01
                WITH DEADBAND 0.1
    ```
  </Tab>

  <Tab title="Digital I/O">
    Read discrete input/output points:

    ```lot theme={null}
    DEFINE ROUTE DiscreteIO WITH TYPE ETHERNETIP
        ADD ETHERNETIP_CONFIG
            WITH IP "192.168.1.100"
            WITH PORT 44818
            WITH POLLING_MS 100
        ADD MAPPING DiscreteInputs
            WITH EVERY 100 MILLISECONDS
            ADD TAG DI_Status1
                WITH ADDRESS "104.1.3.0"
                WITH DATA_TYPE "BOOLEAN"
                WITH SOURCE_TOPIC "io/discrete/in/1"
            ADD TAG DI_Status2
                WITH ADDRESS "104.2.3.0"
                WITH DATA_TYPE "BOOLEAN"
                WITH SOURCE_TOPIC "io/discrete/in/2"
            ADD TAG DO_Command1
                WITH ADDRESS "105.1.3.0"
                WITH DATA_TYPE "BOOLEAN"
                WITH SOURCE_TOPIC "io/discrete/out/1"
            ADD TAG DO_Command2
                WITH ADDRESS "105.2.3.0"
                WITH DATA_TYPE "BOOLEAN"
                WITH SOURCE_TOPIC "io/discrete/out/2"
    ```
  </Tab>

  <Tab title="Assembly Data">
    Read assembly object data:

    ```lot theme={null}
    DEFINE ROUTE AssemblyData WITH TYPE ETHERNETIP
        ADD ETHERNETIP_CONFIG
            WITH IP "192.168.1.100"
            WITH PORT 44818
            WITH POLLING_MS 250
        ADD MAPPING InputAssembly
            WITH EVERY 250 MILLISECONDS
            ADD TAG InputAssembly100
                WITH ADDRESS "4.100.3.0"
                WITH DATA_TYPE "UINT32"
                WITH SOURCE_TOPIC "assembly/input/100"
                WITH PUBLISH_MODE "JSON"
            ADD TAG InputAssembly101
                WITH ADDRESS "4.101.3.0"
                WITH DATA_TYPE "UINT32"
                WITH SOURCE_TOPIC "assembly/input/101"
            ADD TAG OutputAssembly150
                WITH ADDRESS "4.150.3.0"
                WITH DATA_TYPE "UINT32"
                WITH SOURCE_TOPIC "assembly/output/150"
    ```
  </Tab>

  <Tab title="Multi-Rate Polling">
    Different polling rates for different data:

    ```lot theme={null}
    DEFINE ROUTE MultiRateEIP WITH TYPE ETHERNETIP
        ADD ETHERNETIP_CONFIG
            WITH IP "192.168.1.100"
            WITH PORT 44818
        
        ADD MAPPING FastData
            WITH EVERY 100 MILLISECONDS
            ADD TAG CriticalStatus
                WITH ADDRESS "104.1.3.0"
                WITH DATA_TYPE "BOOLEAN"
                WITH SOURCE_TOPIC "fast/status"
            ADD TAG ProcessValue
                WITH ADDRESS "102.1.3.0"
                WITH DATA_TYPE "FLOAT32"
                WITH SOURCE_TOPIC "fast/pv"
        
        ADD MAPPING SlowData
            WITH EVERY 5 SECONDS
            ADD TAG DeviceStatus
                WITH ADDRESS "1.1.5.0"
                WITH DATA_TYPE "UINT16"
                WITH SOURCE_TOPIC "slow/device_status"
            ADD TAG DiagnosticCount
                WITH ADDRESS "1.1.8.0"
                WITH DATA_TYPE "UINT32"
                WITH SOURCE_TOPIC "slow/diagnostic"
    ```
  </Tab>

  <Tab title="Combined (Cyclic + On-Demand)">
    Continuous monitoring with on-demand read and write events in the same route:

    ```lot theme={null}
    DEFINE ROUTE FullEIPSetup WITH TYPE ETHERNETIP
        ADD ETHERNETIP_CONFIG
            WITH IP "192.168.1.100"
            WITH PORT 44818
            WITH POLLING_MS 500
        
        ADD MAPPING AnalogInputs
            WITH EVERY 500 MILLISECONDS
            ADD TAG ProcessValue
                WITH ADDRESS "102.1.3.0"
                WITH DATA_TYPE "FLOAT32"
                WITH SOURCE_TOPIC "eip/analog/pv"
                WITH SCALING_FACTOR 0.01
            ADD TAG Status
                WITH ADDRESS "104.1.3.0"
                WITH DATA_TYPE "BOOLEAN"
                WITH SOURCE_TOPIC "eip/discrete/status"
        
        ADD EVENT ReadAttribute
            WITH SOURCE_TOPIC "eip/commands/read"
            WITH DESTINATION_TOPIC "eip/responses/read"
            WITH QUERY "{operation: READ, address: 1.1.6.0, data_type: UINT32}"
        
        ADD EVENT WriteOutput
            WITH SOURCE_TOPIC "eip/commands/write"
            WITH DESTINATION_TOPIC "eip/responses/write"
            WITH QUERY "{operation: WRITE, address: 103.1.3.0, data_type: FLOAT32, value: 0}"
    ```

    The MAPPING continuously reads an analog input and a discrete status. To trigger an on-demand read (e.g., device serial number), publish any message to `eip/commands/read`. To write an analog output, publish to `eip/commands/write`.
  </Tab>
</Tabs>

***

## CIP Object Reference

<AccordionGroup>
  <Accordion title="Identity Object (Class 1)">
    | Attribute | Description   | Data Type  |
    | --------- | ------------- | ---------- |
    | 1         | Vendor ID     | UINT16     |
    | 2         | Device Type   | UINT16     |
    | 3         | Product Code  | UINT16     |
    | 4         | Revision      | UINT16\[2] |
    | 5         | Status        | UINT16     |
    | 6         | Serial Number | UINT32     |
    | 7         | Product Name  | STRING     |
  </Accordion>

  <Accordion title="Analog Input Point (Class 102)">
    | Attribute | Description     | Data Type     |
    | --------- | --------------- | ------------- |
    | 3         | Value           | FLOAT32/INT16 |
    | 4         | Status          | UINT16        |
    | 5         | Scaling Minimum | FLOAT32       |
    | 6         | Scaling Maximum | FLOAT32       |
  </Accordion>

  <Accordion title="Discrete Input Point (Class 104)">
    | Attribute | Description | Data Type |
    | --------- | ----------- | --------- |
    | 3         | Value       | BOOLEAN   |
    | 4         | Status      | UINT16    |
  </Accordion>

  <Accordion title="Assembly Object (Class 4)">
    | Attribute | Description | Data Type |
    | --------- | ----------- | --------- |
    | 3         | Data        | Variable  |
    | 4         | Size        | UINT16    |
  </Accordion>
</AccordionGroup>

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Connection Failed">
    * Verify IP address is correct
    * Check firewall allows port 44818 (TCP and UDP)
    * Ensure device supports EtherNet/IP explicit messaging
    * Try increasing CONNECTION\_TIMEOUT
  </Accordion>

  <Accordion title="CIP Path Error">
    * Verify ClassID.InstanceID.AttributeID format
    * Check CIP object exists on device
    * Consult device documentation for valid paths
    * Instance usually starts at 1, not 0
  </Accordion>

  <Accordion title="Data Type Mismatch">
    * Verify DATA\_TYPE matches attribute definition
    * Check device documentation for correct types
    * Some devices use INT16 instead of FLOAT32 for analog
  </Accordion>

  <Accordion title="Timeout Errors">
    * Increase READ\_WRITE\_TIMEOUT
    * Check network connectivity
    * Reduce polling rate if device is slow
    * Verify device is not overloaded with connections
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Allen-Bradley" icon="industry" href="./allen-bradley">
    Tag-based access to Allen-Bradley PLCs.
  </Card>

  <Card title="FINS (Omron)" icon="robot" href="./fins">
    Connect to Omron PLCs.
  </Card>
</CardGroup>
