지멘스 S7 드라이버
개요
지멘스 SIMATIC S7 시리즈 (S7-300 / S7-400 / S7-1200 / S7-1500) 의 ISO-on-TCP 통신.
| 항목 | 값 |
|---|---|
opc_type | S7 |
| 구현 클래스 | plantpulse.driver.protocol.s7.S7_34_Driver |
| 라이브러리 | iot-communication (plantpulse.plc.protocol.s7) |
| read | ✅ (배치 모드) |
| write | ✅ (Boolean/Integer/Long/Float/Double/String) |
| 보안 | 없음 (TCP 직결, S7 안전 통신은 미지원) |
OPC 등록 폼
| 필드 | 의미 | 예시 |
|---|---|---|
opc_agent_ip | PLC IP | 192.168.0.70 |
opc_agent_port | ISO-on-TCP 포트 | 102 |
timecycle | 폴링 주기 (ms) | 1000 |
options.controller-type | 시리즈 | S7_400 (default) / S7_300 / S7_200 / S7_200_SMART / S7_1200 / S7_1500 / SINUMERIK_828D |
options.local-rack | rack 번호 (구 오타키 local-lack 도 호환) | 0 (default) |
options.local-slot | slot 번호 | 3 (S7-400 기본) / 0 (S7-1200/1500) / 2 (S7-300) |
options.multi-read | 청크별 1왕복 일괄 read (opt-in) | false (default) |
options.multi-read-max-items | 청크당 아이템 수 상한 | 18 (default, PDU 240 예산) |
rack/slot
- S7-300 : rack=0, slot=2
- S7-400 : rack=0, slot=3 (CPU 슬롯에 따라 다름)
- S7-1200 / 1500 : rack=0, slot=0 (또는 1)
태그 plc_address 형식
지멘스 표준 메모리 주소 표기 (DB / I / Q / M / T / C).
| 표기 | 의미 |
|---|---|
%DB1.DBX0.0 | DB1 의 X0.0 비트 (Bool) |
%DB1.DBB0 | DB1 의 byte 0 (8-bit) |
%DB1.DBW0 | DB1 의 word 0 (16-bit) |
%DB1.DBD0 | DB1 의 double word 0 (32-bit / Real) |
%I0.0 | Input bit 0.0 |
%Q0.0 | Output bit 0.0 |
%M0.0 | Memory bit 0.0 |
%MW100 | Memory word 100 |
%MD100 | Memory double 100 |
iot-communication 라이브러리는 DB1.DBW0 처럼 % 없는 형태도 받지만, 일관성을 위해 % 접두사 권장.
data_type / format 매핑
data_type | format | 매핑 / 비고 |
|---|---|---|
| Boolean / Bool | (empty) | DBX / Ix.y / Mx.y |
| Byte | B / BYTE | DBB / MB |
| Short / Int / Int16 | (empty) | DBW (signed 16-bit) |
| Int32 / DWord | DW / DWORD | DBD (signed 32-bit) |
| UInt32 | UDW | DBD (unsigned) |
| Float / REAL | REAL | DBD 32-bit IEEE float |
| Double / LREAL | LREAL | DB 의 8-byte 영역 |
| String | STR[N] | S7 STRING(2 byte 헤더 + N byte) |
배치 모드 (IS_BATCH_MODE=true) + REQUEST_LIMIT=4 — 한 번의 read 가 4개 주소까지 묶음.
흔한 에러 + 해결
| 메시지 / 증상 | 원인 | 해결 |
|---|---|---|
| Connection refused | ISO-on-TCP (포트 102) 차단 | TIA Portal 의 “Permit access with PUT/GET” 활성화 |
Connection rejected by remote | rack/slot mismatch | 위 표 참고하여 정정 |
Address out of range | DB 가 절대주소 모드 아님 (Optimized) | TIA Portal 에서 DB 속성 → "Optimized block access" OFF |
| 모든 값 0 | DB 번호 / 오프셋 오류 | TIA Portal Watch table 로 동일 주소 read 검증 |
| Bool 만 안 읽힘 | %DB1.DBX0.0 의 .bit 누락 | DBX{byte}.{bit} 표기 정확히 |
curl 등록 예시
S7-1500 / DB1 의 Real 값과 Bool 값을 읽는 예:
curl -X POST http://<edge-host>/api/v1/opc \
-H "Content-Type: application/json" \
-d '{
"opc_id": "OPC_S7_LINE2",
"opc_type": "S7",
"opc_name": "Line2 S7-1500",
"opc_agent_ip": "192.168.0.70",
"opc_agent_port": "102",
"site_id": "SITE_00001",
"auto_collect": true,
"timecycle": 1000,
"options": {
"controller-type": "S7_1500",
"local-rack": "0",
"local-slot": "0"
},
"tag_list": [
{
"tag_id": "OPC_S7_LINE2_TAG_00001",
"tag_name": "Pressure",
"plc_address": "%DB1.DBD0",
"data_type": "Float",
"format": "REAL"
},
{
"tag_id": "OPC_S7_LINE2_TAG_00002",
"tag_name": "RunFlag",
"plc_address": "%DB1.DBX10.0",
"data_type": "Boolean"
}
]
}'
값 read:
curl -s http://<edge-host>/api/v1/tag/OPC_S7_LINE2_TAG_00001/value | jq
예제 모음 (데이터타입별)
지멘스 표준 메모리 영역은 DB / I / Q / M / T / C. iot-communication 라이브러리는 %DB1.DBW0 처럼 % 접두사를 받습니다 (없어도 동작하지만 일관성 위해 권장).
비트 / 불 (Boolean)
data_type | format | plc_address 예 | 의미 |
|---|---|---|---|
Boolean | (empty) | %DB1.DBX0.0 | DB1 byte0 의 bit 0 |
Boolean | (empty) | %DB1.DBX10.7 | DB1 byte10 의 bit 7 |
Boolean | (empty) | %I0.0 | Input bit 0.0 |
Boolean | (empty) | %Q0.0 | Output bit 0.0 |
Boolean | (empty) | %M0.0 | Memory bit 0.0 |
8 / 16-bit 정수
data_type | format | plc_address 예 | 의미 |
|---|---|---|---|
Integer | B | %DB1.DBB0 | byte (8-bit) |
Integer | BYTE | %MB10 | Memory byte 10 |
Integer | (empty) | %DB1.DBW0 | DB word (signed 16) |
Integer | (empty) | %MW100 | Memory word 100 |
32-bit 정수
data_type | format | plc_address 예 | 의미 |
|---|---|---|---|
Integer | DW | %DB1.DBD0 | DB double (signed 32) |
Integer | DWORD | %MD100 | Memory double 100 |
Integer | UDW | %DB1.DBD8 | unsigned 32 |
실수 (Float / Double)
data_type | format | plc_address 예 | 의미 |
|---|---|---|---|
Float | REAL | %DB1.DBD0 | IEEE 754 32-bit (DBD = 4 byte) |
Float | REAL | %MD200 | Memory float 200 |
Double | LREAL | %DB1.DBD8 | IEEE 754 64-bit (8 byte) |
문자열
data_type | format | plc_address 예 | 의미 |
|---|---|---|---|
String | STR[16] | %DB1.DBB100 | S7 STRING (max 16 chars), 헤더 2 byte 포함 |
String | STR[32] | %DB2.DBB0 | S7 STRING, max 32 |
Formula 활용
| 용도 | data_type | fomula | 비고 |
|---|---|---|---|
| 정수 raw → 실수 스케일 | Float | ${VALUE}*0.1 | DBW raw → 실측값 |
| 온도 보정 | Float | ${VALUE}+${TAG_OFFSET} | 캘리브 |
| 압력 단위 변환 (Pa → kPa) | Float | ${VALUE}/1000 | 단위 변환 |
curl 종합 예제
curl -X POST http://<edge-host>/api/v1/opc \
-H "Content-Type: application/json" \
-d '{
"opc_id": "OPC_S7_FULL",
"opc_type": "S7",
"opc_name": "S7-1500 Full",
"opc_agent_ip": "192.168.0.70",
"opc_agent_port": "102",
"site_id": "SITE_00001",
"auto_collect": true,
"timecycle": 1000,
"options": { "controller-type": "S7_1500", "local-rack": "0", "local-slot": "0" },
"tag_list": [
{"tag_id":"OPC_S7_FULL_T01", "tag_name":"DBBit", "plc_address":"%DB1.DBX0.0", "data_type":"Boolean"},
{"tag_id":"OPC_S7_FULL_T02", "tag_name":"InputBit", "plc_address":"%I0.0", "data_type":"Boolean"},
{"tag_id":"OPC_S7_FULL_T03", "tag_name":"DBByte", "plc_address":"%DB1.DBB1", "data_type":"Integer", "format":"B"},
{"tag_id":"OPC_S7_FULL_T04", "tag_name":"DBWord", "plc_address":"%DB1.DBW2", "data_type":"Integer"},
{"tag_id":"OPC_S7_FULL_T05", "tag_name":"DBDouble", "plc_address":"%DB1.DBD4", "data_type":"Integer", "format":"DW"},
{"tag_id":"OPC_S7_FULL_T06", "tag_name":"Pressure", "plc_address":"%DB1.DBD8", "data_type":"Float", "format":"REAL"},
{"tag_id":"OPC_S7_FULL_T07", "tag_name":"Power", "plc_address":"%DB1.DBD12", "data_type":"Double", "format":"LREAL"},
{"tag_id":"OPC_S7_FULL_T08", "tag_name":"BatchName", "plc_address":"%DB1.DBB100", "data_type":"String", "format":"STR[16]"},
{"tag_id":"OPC_S7_FULL_T09", "tag_name":"PressKpa", "plc_address":"%DB1.DBD8", "data_type":"Float", "format":"REAL", "fomula":"${VALUE}/1000"}
]
}'