# PLC Relay

PLC Relay is an edge container service that provides an HTTP API for reading and writing PLC tags. You configure it through the Deployment Manager UI by selecting a protocol, entering connection details, and defining tags.

{% hint style="info" %}
PLC Relay is available exclusively for Enterprise customers. [Contact the Roboflow sales team](https://roboflow.com/sales) to learn more.
{% endhint %}

## Supported Protocols

When adding or editing a PLC Relay service, you select one of three protocols. Each protocol has its own connection settings and tag format.

| Protocol                    | PLCs                                 | Default Port |
| --------------------------- | ------------------------------------ | ------------ |
| Allen-Bradley (EtherNet/IP) | CompactLogix, ControlLogix, Micro800 | 44818        |
| Modbus TCP                  | Any Modbus TCP device                | 502          |
| Siemens S7                  | S7-300, S7-400, S7-1200, S7-1500     | 102          |

{% hint style="warning" %}
Switching protocols clears all configured tags because tag address formats are not interchangeable between protocols. The UI will prompt for confirmation before applying the change.
{% endhint %}

## Connection Settings

### PLC Address

The address format depends on the selected protocol:

* **Allen-Bradley:** IP or hostname, optionally followed by `/slot` (e.g. `192.168.1.100/0`) or a full CIP routing path.
* **Modbus TCP:** IP or hostname, with optional `:port` (e.g. `192.168.1.100:502`). Also requires a Unit ID (0-255) and Word Order (big or little) for 32-bit values.
* **Siemens S7:** IP or hostname, with optional `:port` (e.g. `192.168.1.100:102`). Also requires Rack (0-7) and Slot (0-31).

### Simulation Mode

When enabled, PLC Relay uses an in-memory simulator instead of connecting to a real PLC. All API operations work normally, but values are stored in memory. This is useful for testing without hardware.

## Tag Configuration

Tags define the PLC data points accessible through the API. Each tag has a name, data type, writable flag, and optional description.

### Data Types

| Type   | Description           | Range                           |
| ------ | --------------------- | ------------------------------- |
| `BOOL` | Boolean               | `true` / `false`                |
| `INT`  | 16-bit signed integer | -32,768 to 32,767               |
| `DINT` | 32-bit signed integer | -2,147,483,648 to 2,147,483,647 |
| `REAL` | 32-bit floating point | IEEE 754                        |

### Tag Name Formats

{% tabs %}
{% tab title="Allen-Bradley" %}
Tag names match the PLC program and are case-sensitive.

| Style          | Example                       |
| -------------- | ----------------------------- |
| Simple         | `TagName`                     |
| Program-scoped | `Program:MainProgram.TagName` |
| Array element  | `TagName[0]`                  |
| UDT member     | `MyUDT.Member`                |
| {% endtab %}   |                               |

{% tab title="Modbus TCP" %}
Format: `{area}:{address}` where address is a non-negative integer.

| Area         | Type(s)         | Access    | Example       |
| ------------ | --------------- | --------- | ------------- |
| `coil`       | BOOL            | Writable  | `coil:0`      |
| `discrete`   | BOOL            | Read-only | `discrete:5`  |
| `holding`    | INT, DINT, REAL | Writable  | `holding:100` |
| `input`      | INT, DINT, REAL | Read-only | `input:200`   |
| {% endtab %} |                 |           |               |

{% tab title="Siemens S7" %}
Data Block format: `DB{n}.DB[XWD]{byte}[.{bit}]`

Area format: `[MIQEA][WD]?{byte}[.{bit}]`

| Address         | Type               | Description                     |
| --------------- | ------------------ | ------------------------------- |
| `DB1.DBX0.0`    | BOOL               | Bit 0 of byte 0 in Data Block 1 |
| `DB1.DBW0`      | INT                | 16-bit word in DB1              |
| `DB1.DBD0`      | DINT or REAL       | 32-bit double-word in DB1       |
| `M0.0`          | BOOL               | Merker bit                      |
| `I0.0` / `Q0.0` | BOOL               | Process input/output bit        |
| `MW0` / `MD0`   | INT / DINT or REAL | Merker word / double-word       |

For S7-1200/1500: enable PUT/GET in TIA Portal and disable optimized block access on accessed DBs.
{% endtab %}
{% endtabs %}

## Web Dashboard and REST API

PLC Relay includes a built-in web dashboard for monitoring tag values in real time. Once the service is running, access it at `http://<device-ip>:8007`.

The dashboard also hosts interactive Swagger documentation at `/docs` and a visual config builder at `/static/config-builder.html`.

### API Endpoints

| Method | Path             | Description                                        |
| ------ | ---------------- | -------------------------------------------------- |
| GET    | `/healthz`       | Health check with connection and validation status |
| GET    | `/all_tags`      | Read current values for all tags                   |
| GET    | `/read?tag=name` | Read a single tag by name                          |
| POST   | `/write`         | Write a single tag                                 |
| POST   | `/read_batch`    | Read multiple tags at once                         |
| POST   | `/write_batch`   | Write multiple tags at once                        |
| GET    | `/schema`        | Get all tag definitions                            |
| POST   | `/validate`      | Re-run tag validation against PLC                  |

## Troubleshooting

| Symptom                              | Fix                                                                                                                    |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| "PLC not connected" (Allen-Bradley)  | Verify PLC address format (IP/Slot), check port 44818 is reachable                                                     |
| "PLC not connected" (Modbus)         | Check IP/port (default 502) and verify Unit ID matches the device                                                      |
| "PLC not connected" (Siemens S7)     | Check IP/port (default 102), rack, and slot values; for S7-1200/1500 enable PUT/GET and disable optimized block access |
| "Function refused" (Siemens S7)      | PUT/GET disabled in TIA Portal, or optimized block access enabled on the target DB                                     |
| REAL value reads as garbage (Modbus) | Try the opposite Word Order (big vs. little)                                                                           |
| Validation shows NOT\_FOUND          | Check the PLC program for the exact tag name (case-sensitive)                                                          |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.roboflow.com/deploy/device-manager/plc-relay.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
