EtherNet/IP (Logix) 드라이버
개요
CIP (Common Industrial Protocol) 기반 EtherNet/IP. 주로 Allen-Bradley / Rockwell ControlLogix / CompactLogix PLC 와 통신합니다.
| 항목 | 값 |
|---|---|
opc_type | EIP |
| 구현 클래스 | plantpulse.driver.protocol.eip.EIP_34_Driver |
| 라이브러리 | digitalpetri/ethernet-ip (CipClient + GetAttributeListService) |
| read | ✅ (attribute list raw bytes → String) |
| write | ❌ (별도 service 호출 필요) |
| 보안 | 없음 |
다른 PLC 드라이버와 달리 PLC4j 가 아닌 digitalpetri/ethernet-ip 를 직접 사용합니다 (PLC4jProtocolDriver 가 아니라 BaseProtocolDriver 를 상속).
PLC4j 의 plc4j-driver-eip 도 lib 에 있지만 본 클래스에서는 사용하지 않습니다.
OPC 등록 폼
| 필드 | 의미 | 예시 |
|---|---|---|
opc_agent_ip | PLC IP | 192.168.0.90 |
opc_agent_port | EIP 포트 | 44818 |
timecycle | 폴링 주기 (ms) | 1000 |
options.backplane | backplane 번호 | 1 (default) |
options.local-slot | CPU slot 번호 | 0 (default) |
내부 timeout 은 2 초 고정 (Duration.ofSeconds(2)).
태그 plc_address 형식
EIP 의 raw read 는 CIP class / instance / attribute 좌표로 동작합니다. Edge 에서는 plc_address
필드에 <class>,<instance>,<attribute> 형식 (10진 또는 16진) 으로 입력합니다.
| 표기 | 의미 |
|---|---|
0x6B,1,1 | Symbol class 0x6B, instance 1, attribute 1 |
0x6C,1,1 | Template class |
0x01,1,7 | Identity object 의 Product Name |
Tag1.Member)Logix 에서 흔한 심볼릭 태그 read (MyController:Tag1) 는 별도 service (Read Tag Service) 를
써야 하며 본 드라이버는 raw GetAttributeListService 만 사용합니다. 심볼릭 read 가 필요하면
PLC4j EIP 드라이버로 전환 또는 후속 구현 필요.
data_type / format 매핑
data_type | format | 비고 |
|---|---|---|
| String | (empty) | 응답 raw bytes 그대로 String 으로 누적 |
| Integer / Float / … | (empty) | 후처리에서 캐스팅. 현재 드라이버는 raw bytes → String |
후처리 (PLCValueFomula / Sparkplug DataTypeMapper) 에서 data_type 으로 캐스팅합니다.
흔한 에러 + 해결
| 메시지 / 증상 | 원인 | 해결 |
|---|---|---|
| Connection timeout | 포트 44818 차단, EIP 미가동 | RSLogix / Studio5000 에서 EtherNet/IP module 활성화 |
| Forward Open failure | rack/slot mismatch | options.backplane / options.local-slot 정정 |
Class/Instance not found | 잘못된 class / instance ID | Studio5000 의 Tag Browser 또는 wireshark 로 응답 확인 |
| 값이 깨져 보임 | byte 그대로 String 변환 | 후처리에서 4-byte little-endian 으로 해석하는 fomula 적용 |
curl 등록 예시
curl -X POST http://<edge-host>/api/v1/opc \
-H "Content-Type: application/json" \
-d '{
"opc_id": "OPC_EIP_LOGIX",
"opc_type": "EIP",
"opc_name": "Logix L83E",
"opc_agent_ip": "192.168.0.90",
"opc_agent_port": "44818",
"site_id": "SITE_00001",
"auto_collect": true,
"timecycle": 1000,
"options": {
"backplane": "1",
"local-slot": "0"
},
"tag_list": [
{
"tag_id": "OPC_EIP_LOGIX_TAG_00001",
"tag_name": "ProductName",
"plc_address": "0x01,1,7",
"data_type": "String"
}
]
}'
예제 모음 (데이터타입별)
EIP raw read 는 <class>,<instance>,<attribute> 좌표(10진 또는 0x 접두 16진) 의 raw bytes 를 String 으로 누적합니다. 후처리에서 data_type / fomula 로 캐스팅합니다.
CIP 좌표 형식
plc_address | 의미 |
|---|---|
0x01,1,1 | Identity → Vendor ID |
0x01,1,2 | Identity → Device Type |
0x01,1,7 | Identity → Product Name (String) |
0x6B,1,1 | Symbol Class (Logix tag list) instance 1 attribute 1 |
0x6C,1,1 | Template Class |
0x6C,2,1 | Template Class instance 2 |
0x73,1,1 | Connection Manager |
데이터타입별 매핑
data_type | format | plc_address 예 | 비고 |
|---|---|---|---|
String | (empty) | 0x01,1,7 | Product name (raw bytes 그대로 String) |
Integer | (empty) | 0x01,1,1 | Vendor ID. raw bytes → fomula 로 little-endian 해석 |
Integer | (empty) | 0x01,1,2 | Device Type |
Boolean | (empty) | 0x01,1,8 | Status word (bit 추출은 후처리) |
Float | (empty) | <class>,<inst>,<attr> | 4-byte raw 응답 → 후처리 |
EIP_34_Driver 는 GetAttributeListService 만 호출합니다. 심볼릭 태그 (MyController:Tag1.Member) read 가 필요한 경우에는 ControlLogix Read Tag Service 를 사용하는 별도 구현이 필요합니다. PLC4j EIP 가 lib 에 포함돼 있어 후속 전환이 가능.
Formula 활용
| 용도 | data_type | fomula | 비고 |
|---|---|---|---|
| 정수 raw 보정 | Integer | ${VALUE}*1 | 무변환 통과용 |
| 16-bit 두 값 결합 | Integer | ${TAG_HI}*65536+${VALUE} | hi/lo 두 attribute 합성 |
| 단위 변환 | Float | ${VALUE}*0.1 | raw 정수 스케일 |
curl 종합 예제
curl -X POST http://<edge-host>/api/v1/opc \
-H "Content-Type: application/json" \
-d '{
"opc_id": "OPC_EIP_FULL",
"opc_type": "EIP",
"opc_name": "Logix Full",
"opc_agent_ip": "192.168.0.90",
"opc_agent_port": "44818",
"site_id": "SITE_00001",
"auto_collect": true,
"timecycle": 1000,
"options": { "backplane": "1", "local-slot": "0" },
"tag_list": [
{"tag_id":"OPC_EIP_FULL_T01", "tag_name":"VendorId", "plc_address":"0x01,1,1", "data_type":"Integer"},
{"tag_id":"OPC_EIP_FULL_T02", "tag_name":"DeviceType", "plc_address":"0x01,1,2", "data_type":"Integer"},
{"tag_id":"OPC_EIP_FULL_T03", "tag_name":"ProductName","plc_address":"0x01,1,7", "data_type":"String"},
{"tag_id":"OPC_EIP_FULL_T04", "tag_name":"Status", "plc_address":"0x01,1,5", "data_type":"Integer"}
]
}'