PROFINET Driver
Overview
PROFINET IO — an industrial Ethernet based fieldbus. 2026-07 native rewrite — the old delegation to Apache PLC4j profinet has been removed (PLC4X profinet uses raw Ethernet (EtherType 0x8892, requires libpcap) plus canRead()=false, so connect itself died with an exception on the Edge). It now uses the in-house acyclic Read-Implicit (DCE/RPC over UDP 34964) implementation in plantpulse-plc-protocol (ProfinetPLC) — a service that reads records with ARUUID=0 without an AR (Connect), i.e. the engineering-tool path for I&M data and the like, which fits a polling collector.
| Item | Value |
|---|---|
opc_type | PROFINET |
| Implementation class | plantpulse.driver.protocol.profinet.ProfinetDriver |
| Library | In-house native (profinet of plantpulse-plc-protocol — DCE/RPC Read-Implicit) |
| Inheritance | BaseProtocolDriver (not PLC4j) |
| Default port | 34964 (PROFINET CM DCE/RPC, UDP) |
| Status | Stable (acyclic record polling) |
| read | OK (Read-Implicit, acyclic record) |
| write | ❌ (read-only — Write record not implemented) |
| Security | None |
This driver is for acyclic record polling only. Cyclic IO exchange (RT/IRT, L2 raw Ethernet) is not supported — if you need RT, a separate raw-ethernet (pcap, CAP_NET_RAW) track is required. GSDML files are not used either (record coordinates are specified directly).
Class Structure
BaseProtocolDriver
└── ProfinetDriver — connect() 에서 ProfinetPLC(host, port) 생성 (UDP connectionless)
UDP is connectionless, so there is no handshake — liveness is invalidated on read failure (the AB-ETH/BACnet pattern). Request→response round trips are serialized within ProfinetPLC (one outstanding request), and responses are validated by echoing activityUuid + sequenceNumber to reject stale replies.
OPC Registration Options
| Field | Meaning | Default |
|---|---|---|
opc_agent_ip | PROFINET device IP | 192.168.1.30 |
opc_agent_port | UDP port | 34964 (0 = automatic) |
options.read-timeout | Response timeout (ms) | 3000 |
options.api | PROFINET API number | 0 |
The gsd-directory / dap-id / ip-address options from the old form are not accepted by the native implementation (removed). Record coordinates are specified directly in the tag address.
Tag plc_address Format (new contract)
<slot>:<subslot>:<index>[:<TYPE>]
index: decimal or0xhexadecimal (e.g. I&M0 =0xAFF0)TYPE(defaultWORD):WORD(u16) /INT(i16) /DINT(i32) /DWORD(u32) /REAL(float32) /BOOL/STRING[n](default n=32). Record data is big-endian.
| Notation | Meaning |
|---|---|
0:1:0x0001:REAL | Record 0x0001 of slot0 / subslot1 as float32 |
0:1:2 | Record 2 as WORD (u16) — TYPE omitted |
0:1:0xAFF0:STRING[32] | I&M0 area string |
Support / Not Supported
- read: DCE/RPC Read-Implicit (acyclic record) — OK.
- write: not supported —
isWriteSupported() = falseandwrite()always returnfalse. (Write record is planned.) - Cyclic IO (RT/IRT): not supported — record polling only.
- DCP discovery / automatic IP configuration: not supported — specify the IP directly.
- PROFIsafe / PROFIenergy profiles: not supported.
curl Registration Example
curl -X POST http://<edge-host>/api/v1/opc \
-H "Content-Type: application/json" \
-d '{
"opc_id": "OPC_PROFINET_IO1",
"opc_type": "PROFINET",
"opc_name": "PN Device 1",
"opc_agent_ip": "192.168.1.30",
"opc_agent_port": "34964",
"site_id": "SITE_00001",
"auto_collect": true,
"timecycle": 1000,
"options": { "read-timeout": "3000" },
"tag_list": [
{"tag_id":"OPC_PROFINET_IO1_T01","tag_name":"Rec1","plc_address":"0:1:0x0001:REAL","data_type":"Float"},
{"tag_id":"OPC_PROFINET_IO1_T02","tag_name":"Rec2","plc_address":"0:1:2:WORD","data_type":"Integer"}
]
}'
References
- Profinet IO — IEC 61158-6-10 / IEC 61784. Read-Implicit = CM opnum 5.
- Code:
plantpulse-edge-driver/src/plantpulse/driver/protocol/profinet/ProfinetDriver.java+ theprofinetpackage ofplantpulse-plc-protocol. - Operations: if the goal is collecting S7 PLC memory values, the S7 (ISO-on-TCP) driver is more common — this driver is for polling records (I&M, etc.) of PROFINET devices.