> For the complete documentation index, see [llms.txt](https://docs.roboflow.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.roboflow.com/deployment/ko/self-hosted/enterprise/deployment-manager/services/plc-relay.md).

# PLC Relay

Allen-Bradley, Modbus TCP 또는 Siemens S7을 통해 PLC 태그를 읽고 쓰도록 PLC Relay를 구성합니다.

PLC Relay는 PLC 태그를 읽고 쓰기 위한 HTTP API를 제공하는 엣지 컨테이너 서비스입니다. Deployment Manager UI에서 프로토콜을 선택하고, 연결 세부 정보를 입력하며, 태그를 정의하여 구성합니다.

{% hint style="info" %}
PLC Relay는 Enterprise 고객 전용으로 제공됩니다. [Roboflow 영업팀에 문의하세요](https://roboflow.com/sales) 자세한 내용을 알아보세요.
{% endhint %}

## 지원되는 프로토콜

PLC Relay 서비스를 추가하거나 편집할 때 세 가지 프로토콜 중 하나를 선택합니다. 각 프로토콜에는 자체 연결 설정과 태그 형식이 있습니다.

<table data-header-hidden data-search="false"><thead><tr><th></th><th></th><th></th><th></th></tr></thead><tbody><tr><td>프로토콜</td><td><code>PLC_DRIVER</code></td><td>PLC</td><td>기본 포트</td></tr><tr><td>Allen-Bradley(EtherNet/IP)</td><td><code>allen_bradley</code></td><td>CompactLogix, ControlLogix, Micro800</td><td>44818</td></tr><tr><td>Modbus TCP</td><td><code>modbus</code></td><td>모든 Modbus TCP 장치</td><td>502</td></tr><tr><td>Siemens S7</td><td><code>siemens_s7</code></td><td>S7-300, S7-400, S7-1200, S7-1500</td><td>102</td></tr></tbody></table>

{% hint style="warning" %}
프로토콜 간에는 태그 주소 형식을 서로 교환할 수 없으므로 프로토콜을 전환하면 구성된 모든 태그가 삭제됩니다. UI는 변경 사항을 적용하기 전에 확인을 요청합니다.
{% endhint %}

## 연결 설정

### PLC 주소

주소 형식은 선택한 프로토콜에 따라 달라집니다:

* **Allen-Bradley:** IP 또는 호스트 이름 뒤에 선택적으로 `/slot` (예: `192.168.1.100/0`) 또는 전체 CIP 라우팅 경로.
* **Modbus TCP:** 선택적 `:port가 포함된 IP 또는 호스트 이름` (예: `192.168.1.100:502`). 또한 32비트 값에는 Unit ID(0\~255)와 워드 순서(빅 엔디언 또는 리틀 엔디언)가 필요합니다.
* **Siemens S7:** 선택적 `:port가 포함된 IP 또는 호스트 이름` (예: `192.168.1.100:102`). 또한 Rack(0\~7) 및 Slot(0\~31)이 필요합니다.

### 시뮬레이션 모드

활성화하면 PLC Relay는 실제 PLC에 연결하는 대신 메모리 내 시뮬레이터를 사용합니다. 모든 API 작업은 정상적으로 작동하지만 값은 메모리에 저장됩니다. 하드웨어 없이 테스트할 때 유용합니다.

## 태그 구성

태그는 API를 통해 액세스할 수 있는 PLC 데이터 포인트를 정의합니다. 각 태그에는 이름, 데이터 유형, 쓰기 가능 플래그 및 선택적 설명이 있습니다.

### 데이터 유형

| 유형     | 설명            | 범위                            |
| ------ | ------------- | ----------------------------- |
| `BOOL` | 부울            | `true` / `false`              |
| `INT`  | 16비트 부호 있는 정수 | -32,768\~32,767               |
| `DINT` | 32비트 부호 있는 정수 | -2,147,483,648\~2,147,483,647 |
| `REAL` | 32비트 부동 소수점   | IEEE 754                      |

### 태그 이름 형식

{% tabs %}
{% tab title="Allen-Bradley" %}
태그 이름은 PLC 프로그램과 일치해야 하며 대소문자를 구분합니다.

| 스타일          | 예시                            |
| ------------ | ----------------------------- |
| 단순           | `TagName`                     |
| 프로그램 범위      | `Program:MainProgram.TagName` |
| 배열 요소        | `TagName[0]`                  |
| UDT 멤버       | `MyUDT.Member`                |
| {% endtab %} |                               |

{% tab title="Modbus TCP" %}
형식: `{area}:{address}` 여기서 address는 음수가 아닌 정수입니다.

| 영역           | 유형              | 액세스   | 예시            |
| ------------ | --------------- | ----- | ------------- |
| `코일`         | BOOL            | 쓰기 가능 | `coil:0`      |
| `이산 입력`      | BOOL            | 읽기 전용 | `discrete:5`  |
| `홀딩`         | INT, DINT, REAL | 쓰기 가능 | `holding:100` |
| `입력`         | INT, DINT, REAL | 읽기 전용 | `input:200`   |
| {% endtab %} |                 |       |               |

{% tab title="Siemens S7" %}
데이터 블록 형식: `DB{n}.DB[XWD]{byte}[.{bit}]`

영역 형식: `[MIQEA][WD]?{byte}[.{bit}]`

| 주소              | 유형                 | 설명                       |
| --------------- | ------------------ | ------------------------ |
| `DB1.DBX0.0`    | BOOL               | 데이터 블록 1의 바이트 0에 있는 비트 0 |
| `DB1.DBW0`      | INT                | DB1의 16비트 워드             |
| `DB1.DBD0`      | DINT 또는 REAL       | DB1의 32비트 더블 워드          |
| `M0.0`          | BOOL               | 메르커 비트                   |
| `I0.0` / `Q0.0` | BOOL               | 프로세스 입력/출력 비트            |
| `MW0` / `MD0`   | INT / DINT 또는 REAL | 메르커 워드 / 더블 워드           |

S7-1200/1500의 경우: TIA Portal에서 PUT/GET을 활성화하고 액세스되는 DB의 최적화된 블록 액세스를 비활성화하세요.
{% endtab %}
{% endtabs %}

## 웹 대시보드

PLC Relay에는 태그 값을 실시간으로 모니터링하는 기본 제공 웹 대시보드가 포함되어 있습니다. 서비스가 실행되면 다음에서 액세스하세요. `http://<device-ip>:8007`.

대시보드는 다음 위치에서 대화형 Swagger 문서도 호스팅합니다. `/docs` 그리고 다음 위치에 시각적 구성 빌더가 있습니다. `/static/config-builder.html`.

## HTTP API

API는 HTTP를 통해 구성된 태그를 읽고 쓰므로, 파이프라인은 Allen-Bradley EtherNet/IP, Modbus TCP 또는 Siemens S7과 직접 통신하지 않고도 PLC 데이터를 교환할 수 있습니다. 기본 URL은 `http://<device-ip>:8007`, API는 인증을 사용하지 않습니다. 다음을 참조하세요. [서비스](/deployment/ko/self-hosted/enterprise/deployment-manager/services.md#using-the-apis) 모든 온디바이스 서비스 API에 공통으로 적용되는 규칙을 확인하세요.

태그는 서비스의 `PLC_TAGS` 환경 변수에서 가져오며 API를 통해 생성하거나 변경할 수 없습니다. 값만 쓸 수 있으며, 쓰기 가능으로 구성된 태그에만 쓸 수 있습니다.

### 상태 코드를 신뢰하기 전에 읽으세요

서비스에 도달했지만 PLC에서 실패한 요청은 다음을 반환합니다. `200`. 본문을 확인하세요:

* `/read` 은 다음을 반환합니다. `value: null` 와 함께 `error` 가 채워집니다.
* `/write` 은 다음을 반환합니다. `success: false` 와 함께 `error` 가 채워집니다.
* `/healthz` 은 다음을 반환합니다. `plc_connected: false`.

실제 `4xx` 응답은 요청 자체에 문제가 있음을 의미합니다: `404` 구성되지 않은 태그의 경우, `403` 읽기 전용으로 구성된 태그의 경우, `400` 빈 배치 또는 쓰기 배치에서 중복 태그 이름의 경우, `422` 유효성 검사에 실패한 본문 또는 쿼리 매개변수의 경우.

### 상태 및 유효성 검사

`/healthz` 은 활성 드라이버, 릴레이가 `라이브` 또는 `시뮬레이션` 모드인지 여부 및 최신 태그 유효성 검사 요약도 보고합니다. 유효성 검사는 구성된 각 태그를 PLC와 비교하여 다음 상태로 보고합니다. `ok`, `not_found`, `type_mismatch`, 또는 `not_validated`.

{% openapi src="/files/77e1ab3c53d5d0cbb663ea227bdd37cbd6f1f1cd" path="/healthz" method="get" %}
[edge-plc-relay.yaml](https://1826078061-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-bc81a2258bd5eefa9b64b301eac0797c0f01e796%2Fedge-plc-relay.yaml?alt=media)
{% endopenapi %}

PLC 프로그램 변경 또는 재연결 후 유효성 검사를 다시 실행하세요:

{% openapi src="/files/77e1ab3c53d5d0cbb663ea227bdd37cbd6f1f1cd" path="/validate" method="post" %}
[edge-plc-relay.yaml](https://1826078061-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-bc81a2258bd5eefa9b64b301eac0797c0f01e796%2Fedge-plc-relay.yaml?alt=media)
{% endopenapi %}

### 태그 정의

태그 이름은 활성 드라이버 형식의 PLC 주소이며, 다음에 설명되어 있습니다. [태그 이름 형식](#tag-name-formats).

{% openapi src="/files/77e1ab3c53d5d0cbb663ea227bdd37cbd6f1f1cd" path="/schema" method="get" %}
[edge-plc-relay.yaml](https://1826078061-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-bc81a2258bd5eefa9b64b301eac0797c0f01e796%2Fedge-plc-relay.yaml?alt=media)
{% endopenapi %}

### 값 읽기 및 쓰기

```bash
curl "http://<device-ip>:8007/read?tag=Station1.CycleCount"

curl -X POST http://<device-ip>:8007/write \
  -H "Content-Type: application/json" \
  -d '{"name": "Station1.CycleCount", "value": 42}'
```

{% openapi src="/files/77e1ab3c53d5d0cbb663ea227bdd37cbd6f1f1cd" path="/all\_tags" method="get" %}
[edge-plc-relay.yaml](https://1826078061-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-bc81a2258bd5eefa9b64b301eac0797c0f01e796%2Fedge-plc-relay.yaml?alt=media)
{% endopenapi %}

{% openapi src="/files/77e1ab3c53d5d0cbb663ea227bdd37cbd6f1f1cd" path="/read" method="get" %}
[edge-plc-relay.yaml](https://1826078061-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-bc81a2258bd5eefa9b64b301eac0797c0f01e796%2Fedge-plc-relay.yaml?alt=media)
{% endopenapi %}

{% openapi src="/files/77e1ab3c53d5d0cbb663ea227bdd37cbd6f1f1cd" path="/write" method="post" %}
[edge-plc-relay.yaml](https://1826078061-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-bc81a2258bd5eefa9b64b301eac0797c0f01e796%2Fedge-plc-relay.yaml?alt=media)
{% endopenapi %}

### 배치 작업

두 배치 엔드포인트는 실행 전에 전체 단위로 유효성을 검사하므로, 알 수 없는 태그가 있을 경우 부분 결과를 반환하는 대신 전체 요청이 거부됩니다.

`/write_batch` 는 동일한 태그를 두 번 지정한 배치도 추가로 거부합니다. 반복된 이름에 대해 마지막 값만 유지하면 이전 쓰기가 조용히 삭제되기 때문입니다. `/read_batch` 는 중복을 허용하고 전송한 순서대로 항목당 하나의 결과를 반환합니다.

유효성 검사 후 발생하는 PLC 실패는 항목별로 `write_batch`의 `결과`에 보고되며, `success_count` 및 `error_count` 가 배치를 요약합니다.

```bash
curl -X POST http://<device-ip>:8007/read_batch \
  -H "Content-Type: application/json" \
  -d '{"tags": ["Station1.PartPresent", "Station1.CycleCount"]}'
```

{% openapi src="/files/77e1ab3c53d5d0cbb663ea227bdd37cbd6f1f1cd" path="/read\_batch" method="post" %}
[edge-plc-relay.yaml](https://1826078061-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-bc81a2258bd5eefa9b64b301eac0797c0f01e796%2Fedge-plc-relay.yaml?alt=media)
{% endopenapi %}

{% openapi src="/files/77e1ab3c53d5d0cbb663ea227bdd37cbd6f1f1cd" path="/write\_batch" method="post" %}
[edge-plc-relay.yaml](https://1826078061-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoksNmwps1HmYr8TqHDnX%2Fuploads%2Fgit-blob-bc81a2258bd5eefa9b64b301eac0797c0f01e796%2Fedge-plc-relay.yaml?alt=media)
{% endopenapi %}

## CLI

이 `plc-cli` 도구는 태그를 읽고 쓰기 위한 대화형 터미널 인터페이스를 제공합니다. 웹 대시보드에 연결할 수 없을 때 디버깅 및 빠른 작업에 사용하세요. 대시보드가 사용하는 동일한 HTTP API에 대해 컨테이너 내부에서 실행되는 로컬 클라이언트입니다.

```bash
docker exec -it plc-relay plc-cli
```

<table data-search="false"><thead><tr><th>키</th><th>동작</th></tr></thead><tbody><tr><td><code>R</code></td><td>모든 태그 값 읽기</td></tr><tr><td><code>T</code></td><td>목록에서 선택한 단일 태그 읽기</td></tr><tr><td><code>W</code></td><td>쓰기 가능한 태그에서 선택한 태그 쓰기</td></tr><tr><td><code>S</code></td><td>태그 스키마 표시</td></tr><tr><td><code>H</code></td><td>상세 상태 정보 표시</td></tr><tr><td><code>V</code></td><td>PLC에 대해 태그 유효성 검사 실행</td></tr><tr><td><code>Enter</code></td><td>화면 새로 고침</td></tr><tr><td><code>Q</code></td><td>종료</td></tr></tbody></table>

## 환경 변수

구성 모달이 이러한 값을 대신 작성합니다. 배포를 수동으로 관리하는 경우에만 직접 편집하세요. 다음을 참조하세요. [장치 구성 업데이트](/deployment/ko/self-hosted/enterprise/deployment-manager/making-changes/update-device-configuration.md).

<table data-search="false"><thead><tr><th>변수</th><th>기본값</th><th>설명</th></tr></thead><tbody><tr><td><code>PLC_DRIVER</code></td><td>없음</td><td><code>allen_bradley</code>, <code>modbus</code>, 또는 <code>siemens_s7</code></td></tr><tr><td><code>PLC_IP</code></td><td>없음</td><td>선택한 드라이버 형식의 PLC 주소</td></tr><tr><td><code>PLC_TAGS</code></td><td>없음</td><td>JSON 형식의 태그 정의. 다음 위치의 구성 빌더가 <code>/static/config-builder.html</code> 이를 생성합니다</td></tr><tr><td><code>SIMULATION_MODE</code></td><td>꺼짐</td><td>실제 PLC 대신 메모리 내 시뮬레이터 사용</td></tr><tr><td><code>LOG_LEVEL</code></td><td><code>INFO</code></td><td>로깅 상세 수준: <code>DEBUG</code>, <code>INFO</code>, <code>WARNING</code>, 또는 <code>ERROR</code></td></tr></tbody></table>

드라이버별 설정:

<table data-search="false"><thead><tr><th>드라이버</th><th>변수</th><th>범위</th><th>기본값</th></tr></thead><tbody><tr><td>Modbus</td><td><code>MODBUS_UNIT_ID</code></td><td>0~255</td><td><code>1</code></td></tr><tr><td>Modbus</td><td><code>MODBUS_WORD_ORDER</code></td><td><code>빅 엔디언</code> 또는 <code>리틀 엔디언</code></td><td><code>빅 엔디언</code></td></tr><tr><td>Siemens S7</td><td><code>S7_RACK</code></td><td>0~7</td><td><code>0</code></td></tr><tr><td>Siemens S7</td><td><code>S7_SLOT</code></td><td>0~31</td><td><code>1</code></td></tr></tbody></table>

## 연결 모니터링

장치 페이지에는 현재 연결 상태, 활성 프로토콜 및 최신 태그 값을 포함하는 실시간 PLC Relay 상태 카드가 표시됩니다. 릴레이가 PLC에 연결할 수 없는 경우 카드에 연결 불가 배너가 표시됩니다.

릴레이의 연결이 끊어질 때 알림을 받으려면 장치의 "Device Alerts" 탭에서 "PLC Disconnected" 알림을 추가하세요. 다음을 참조하세요. [장치 알림 설정](/deployment/ko/self-hosted/enterprise/deployment-manager/setting-up/set-up-device-alerts.md).

## 문제 해결

| 증상                                 | 해결 방법                                                                                      |
| ---------------------------------- | ------------------------------------------------------------------------------------------ |
| "PLC not connected"(Allen-Bradley) | PLC 주소 형식(IP/Slot)을 확인하고 포트 44818에 연결할 수 있는지 확인하세요                                         |
| "PLC not connected"(Modbus)        | IP/포트(기본값 502)를 확인하고 Unit ID가 장치와 일치하는지 확인하세요                                              |
| "PLC not connected"(Siemens S7)    | IP/포트(기본값 102), rack 및 slot 값을 확인하세요. S7-1200/1500의 경우 PUT/GET을 활성화하고 최적화된 블록 액세스를 비활성화하세요 |
| "Function refused"(Siemens S7)     | TIA Portal에서 PUT/GET이 비활성화되었거나 대상 DB에서 최적화된 블록 액세스가 활성화됨                                   |
| REAL 값이 잘못된 값으로 읽힘(Modbus)         | 반대 워드 순서(빅 엔디언 대 리틀 엔디언)를 시도하세요                                                            |
| 유효성 검사에 NOT\_FOUND가 표시됨            | 정확한 태그 이름을 PLC 프로그램에서 확인하세요(대소문자 구분)                                                       |
