Skip to main content

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.

ItemValue
opc_typePROFINET
Implementation classplantpulse.driver.protocol.profinet.ProfinetDriver
LibraryIn-house native (profinet of plantpulse-plc-protocol — DCE/RPC Read-Implicit)
InheritanceBaseProtocolDriver (not PLC4j)
Default port34964 (PROFINET CM DCE/RPC, UDP)
StatusStable (acyclic record polling)
readOK (Read-Implicit, acyclic record)
write❌ (read-only — Write record not implemented)
SecurityNone
Acyclic records only — cyclic RT not supported

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

FieldMeaningDefault
opc_agent_ipPROFINET device IP192.168.1.30
opc_agent_portUDP port34964 (0 = automatic)
options.read-timeoutResponse timeout (ms)3000
options.apiPROFINET API number0
Old PLC4X options removed

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 or 0x hexadecimal (e.g. I&M0 = 0xAFF0)
  • TYPE (default WORD): WORD (u16) / INT (i16) / DINT (i32) / DWORD (u32) / REAL (float32) / BOOL / STRING[n] (default n=32). Record data is big-endian.
NotationMeaning
0:1:0x0001:REALRecord 0x0001 of slot0 / subslot1 as float32
0:1:2Record 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 supportedisWriteSupported() = false and write() always return false. (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 + the profinet package of plantpulse-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.