DNP3 Driver
Overview
IEEE 1815 standard DNP3 (Distributed Network Protocol). The de facto standard for electric/water/gas utility SCADA. A master (client) opens a TCP connection to an outstation (server) and collects measured values (Analog Input / Binary Input / Counter) via Application Layer READ.
| Item | Value |
|---|---|
opc_type | DNP3 |
| Implementation class | plantpulse.driver.protocol.dnp3.DNP3Driver |
| Library | In-house Java implementation (no external dependencies) |
| read | ✅ (single point + class poll) |
| write | ✅ (G12V1 CROB, G41V1–V4 Analog Output) |
| Security | None (DNP3-SA not implemented) |
| Default port | 20000 (TCP) |
Class Structure
| Class | Role |
|---|---|
DNP3Driver | TCP socket / AL+TL+DLL assembly / single-point read / class poll / write |
DnpDataLink | 10-byte DLL header (start 0x05 0x64) + LE CRC per 16-byte block |
DnpTransport | 1-byte TL header (FIN/FIR/SEQ 6-bit) |
DnpApplication | Function Code, IIN, object header, qualifier, response parser |
DnpObject | Object encoders/decoders for Groups 1/2/10/12/20/30/32/40/41 |
DnpCrc | DNP3-specific CRC-16 (poly 0x3D65, reflected 0xA6BC, ~complement, LE serialization) |
DnpAddress | gNvM.idx / classN address parser |
Wire Format
TCP payload =
DLL header(10 byte: start 0x0564 + len + ctl + dst LE + src LE + CRC LE)
+ 16-byte 블록마다 user data + LE CRC
↳ TL byte (1: FIN/FIR + SEQ 0..63)
↳ AL bytes:
byte 0 App Control (FIR/FIN/CON/UNS + SEQ 0..15)
byte 1 Function Code (1=READ, 5=DIRECT_OPERATE, 129=RESPONSE)
byte 2.. Object header (group + variation + qualifier) + range/data
CRC: DnpCrc.compute(data) — table-driven, init 0, reflected 0xA6BC, final ~crc, serialized as 2 bytes LE.
Verified vector: [05 64 05 C9 01 00 00 04] → CRC 0xE521 (LE 21 E5).
OPC Registration Options
| Field | Meaning | Default |
|---|---|---|
opc_agent_ip / opc_agent_port | outstation IP / port | 20000 if port is 0 |
options.master-address | DNP3 master DLL address | 1 |
options.outstation-address | outstation DLL address | 10 |
options.connect-timeout | TCP connect timeout (ms) | 3000 |
options.read-timeout | read SO timeout (ms) | 5000 |
Tag plc_address Format
| Notation | Meaning |
|---|---|
g30v1.5 | Group 30 Var 1, point 5 — Analog Input 32-bit signed (with flag) |
g30v5.0 | Analog Input 32-bit float |
g30v6.0 | Analog Input 64-bit double |
g1v2.0 | Binary Input 0 (with flag) |
g20v1.0 | 32-bit Counter |
g40v1.0 | Analog Output 32-bit |
class0 | Integrity poll (G60V1) — Static + all classes |
class1 – class3 | Event class poll (G60V2/V3/V4) |
A class poll fires once and then caches the response (lastValueByKey). A subsequent single-point read returns immediately on a cache hit.
Write address (g12v1.N + value):
| Input value | CROB op |
|---|---|
Latch_On or 1 | opType=3 (Latch_On), TCC=0 |
Latch_Off or 0 | opType=4 (Latch_Off), TCC=0 |
Pulse_On:<onMs>:<offMs>:<count> | opType=1 |
Close / Trip | TCC=1 (Close) / TCC=2 (Trip) |
g41v1..g41v4 are 32-bit signed / 16-bit signed / 32-bit float / 64-bit double Analog Output respectively.
Unsupported Areas
- DNP3-SA (Secure Authentication, IEEE 1815-2012 §7).
- Multi-segment TL responses (currently transmits single-segment FIR=FIN=1 only).
- Asynchronous reception of unsolicited responses (FC 130) — transmission is possible, but no client-side unsolicited handler is implemented.
- File transfer (FC 25-30), time sync (FC 23 DELAY_MEASURE is defined as a constant only).
Test Coverage
test/java/plantpulse/driver/protocol/dnp3/
| Test | Verifies |
|---|---|
DnpCrcTest | spec vector + arbitrary-length CRC |
DnpDataLinkTest | 10-byte header + block CRC round-trip |
DnpTransportTest | FIN/FIR/SEQ encoding |
DnpApplicationTest / DnpApplicationWriteTest | READ/DIRECT_OPERATE build, IIN decode |
DnpObjectTest / DnpObjectWriteTest | G1/G30/G40/G12V1/G41 encoder/decoder |
DnpAddressTest / DnpAddressWriteTest | address parser |
DNP3DriverTest | read/write end-to-end against a mock outstation |
DnpSpecExtraTest | additional spec conformance |
References
- IEEE 1815-2012, "DNP3 Specification".
- Code:
plantpulse-edge-driver/src/plantpulse/driver/protocol/dnp3/. - Operation: the master/outstation addresses must match those on the outstation side. If they do not match, the frame is discarded immediately at the DLL header.