DNP3 ドライバ
概要
IEEE 1815 標準の DNP3 (Distributed Network Protocol)。電力/水道/ガスの utility SCADA における事実上の標準。 Master(client) が outstation(server) へ TCP 接続し、Application Layer READ で測定値 (Analog Input / Binary Input / Counter) を収集する。
| 項目 | 値 |
|---|---|
opc_type | DNP3 |
| 実装クラス | plantpulse.driver.protocol.dnp3.DNP3Driver |
| ライブラリ | 独自 Java 実装 (外部依存なし) |
| read | ✅ (単一ポイント + class poll) |
| write | ✅ (G12V1 CROB, G41V1〜V4 Analog Output) |
| セキュリティ | なし (DNP3-SA 未実装) |
| デフォルトポート | 20000 (TCP) |
クラス構成
| クラス | 役割 |
|---|---|
DNP3Driver | TCP socket / AL+TL+DLL 組み立て / 単一ポイント read / class poll / write |
DnpDataLink | 10-byte DLL ヘッダ (start 0x05 0x64) + 16-byte ブロックごとの LE CRC |
DnpTransport | 1-byte TL ヘッダ (FIN/FIR/SEQ 6-bit) |
DnpApplication | Function Code, IIN, Object header, qualifier, response パーサ |
DnpObject | Group 1/2/10/12/20/30/32/40/41 のオブジェクトエンコーダ/デコーダ |
DnpCrc | DNP3 専用 CRC-16 (poly 0x3D65, reflected 0xA6BC, ~complement, LE シリアライズ) |
DnpAddress | gNvM.idx / classN アドレスパーサ |
Wire フォーマット
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、最後に ~crc、LE 2 byte シリアライズ。
検証済み vector: [05 64 05 C9 01 00 00 04] → CRC 0xE521 (LE 21 E5)。
OPC 登録オプション
| フィールド | 意味 | デフォルト |
|---|---|---|
opc_agent_ip / opc_agent_port | outstation IP / ポート | port が 0 の場合は 20000 |
options.master-address | DNP3 master DLL アドレス | 1 |
options.outstation-address | outstation DLL アドレス | 10 |
options.connect-timeout | TCP connect タイムアウト (ms) | 3000 |
options.read-timeout | read SO タイムアウト (ms) | 5000 |
タグ plc_address 形式
| 表記 | 意味 |
|---|---|
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 + 全クラス |
class1 〜 class3 | Event class poll (G60V2/V3/V4) |
class poll は一度 fire した後、応答をキャッシュする (lastValueByKey)。後続の単一ポイント read がキャッシュヒットすれば即座に返す。
write アドレス (g12v1.N + value):
| 入力 value | CROB op |
|---|---|
Latch_On または 1 | opType=3 (Latch_On), TCC=0 |
Latch_Off または 0 | opType=4 (Latch_Off), TCC=0 |
Pulse_On:<onMs>:<offMs>:<count> | opType=1 |
Close / Trip | TCC=1 (Close) / TCC=2 (Trip) |
g41v1..g41v4 はそれぞれ 32-bit signed / 16-bit signed / 32-bit float / 64-bit double の Analog Output。
未サポート範囲
- DNP3-SA (Secure Authentication, IEEE 1815-2012 §7)。
- Multi-segment TL 応答 (現在は single-segment FIR=FIN=1 の送信のみ)。
- Unsolicited responses (FC 130) の非同期受信 — 送信は可能だが、クライアント側の unsolicited handler は未実装。
- File transfer (FC 25-30)、Time sync (FC 23 DELAY_MEASURE は定数のみ定義)。
テストカバレッジ
test/java/plantpulse/driver/protocol/dnp3/
| テスト | 検証内容 |
|---|---|
DnpCrcTest | spec vector + 任意長の CRC |
DnpDataLinkTest | 10-byte ヘッダ + block CRC ラウンドトリップ |
DnpTransportTest | FIN/FIR/SEQ エンコーディング |
DnpApplicationTest / DnpApplicationWriteTest | READ/DIRECT_OPERATE のビルド、IIN デコード |
DnpObjectTest / DnpObjectWriteTest | G1/G30/G40/G12V1/G41 エンコーダ/デコーダ |
DnpAddressTest / DnpAddressWriteTest | アドレスパーサ |
DNP3DriverTest | mock outstation による read/write のエンドツーエンド |
DnpSpecExtraTest | 追加の spec 適合性 |
参考
- IEEE 1815-2012, "DNP3 Specification"。
- コード:
plantpulse-edge-driver/src/plantpulse/driver/protocol/dnp3/。 - 運用: outstation 側の master/outstation address の整合が必須。一致しない場合は DLL ヘッダの時点で即座に破棄される。