M-Bus ドライバ
概要
M-Bus (Meter-Bus、EN 13757-2/3) の独自 Java native 実装。運用環境で一般的な wired M-Bus master ゲートウェイ、または シリアル-TCP コンバータ (Moxa NPort、USR-TCP232 など) に TCP socket で接続し、標準 M-Bus フレームを送受信します。
| 項目 | 値 |
|---|---|
opc_type | MBUS |
| 実装クラス | plantpulse.driver.protocol.mbus.MBusDriver |
| ライブラリ | (なし — 独自実装。EN 13757-2/3) |
| read | 良好 (REQ_UD2 → RSP_UD) |
| write | 良好 (Slave Selection / Application Reset) |
| デフォルトポート | 10001 (Moxa NPort デフォルト) |
| セキュリティ | なし |
クラス / 構造
MBusDriver (BaseProtocolDriver)
├── Socket / DataInputStream / OutputStream
├── defaultAddress — primary 1~250 (옵션)
├── synchronized requestUd2 / sendSlaveSelection / sendAppReset
├── MBusFrame — buildSndNke / buildReqUd2 / buildSlaveSelection
│ buildSndUdAppReset / parseLongFrame / parseAck
│ ACK=0xE5, START_LONG=0x68, SECONDARY_ADDRESS=253
├── MBusChecksum — sum(c+a+ci+data) mod 256
├── MBusBcd — encodeIdToBcd4(long), BCD 디코드
└── MBusDataRecord — DIF/VIF 파싱, parseAll(buf, off, len) → List<Record>
(Record { value, multiplier, unit, ... })
connect() :
- TCP 接続 (host:10001)。
- SND_NKE (Short Frame, C=0x40, A=
default-address) を送信。 - ACK (0xE5) 受信の検証 — 応答がなくても connected=true (ゲートウェイにより差異あり)。
wire フォーマット概要
Short Frame (SND_NKE / Slave Selection 応答 ACK)
0x10 | C(1) | A(1) | CS(1) | 0x16
ACK 단독 = 0xE5
Long Frame (REQ_UD2 / RSP_UD)
0x68 | L | L | 0x68 | C(1) | A(1) | CI(1) | data... | CS(1) | 0x16
L = C + A + CI + data 의 byte 수
CS = (C+A+CI+data) mod 256
| コマンド | C | CI | 意味 |
|---|---|---|---|
| SND_NKE | 0x40 | — | Initialize slave |
| REQ_UD2 | 0x5B | — | User data 要求 |
| Slave Selection | 0x53 | 0x52 | Secondary addressing |
| App Reset | 0x53 | 0x50 | Application reset |
OPC 登録オプション (options)
| キー | 意味 | デフォルト |
|---|---|---|
default-address | primary address (1~250) | 1 |
connect-timeout | ms | 3000 |
read-timeout | ms | 3000 |
タグアドレス形式
Primary addressing
| 表記 | 意味 |
|---|---|
1:0 | primary 1、1 番目の record |
5:2 | primary 5、3 番目の record |
1 | primary 1、user-data 全体の hex |
Secondary addressing
| 表記 | 意味 |
|---|---|
secondary:12345678AB1C0107 | 16 hex 文字 (ID 4 + Mfg 2 + Ver 1 + Med 1) |
secondary:<16-hex>:<recordIndex> | 上記 + record インデックス |
select:12345678:43932:1:7 | 十進エイリアス (id, mfg, ver, med) |
select:12345678:43932:1:7:0 | + record インデックス |
trySecondaryAddress() は secondary slave selection を先に送信 → primary=253 で REQ_UD2。
ID は EN 13757-3 wire format の LSB-first BCD でエンコードされます (MBusBcd.encodeIdToBcd4)。
write アドレス形式
| 表記 | 動作 |
|---|---|
secondary:<hex> / select:<id>:<mfg>:<ver>:<med> | Slave selection のみ送信 |
app-reset:<subcode> | primary=default-address に application reset |
app-reset:<primary>:<subcode> | primary を明示 |
select-and-reset:<id>:<mfg>:<ver>:<med>:<subcode> | secondary 選択後に reset |
subcode は address.value でも受け付けます。
record デコード
MBusDataRecord.parseAll(userData, off=12, len) が user-data (header 12 byte 以降) を DIF/VIF ベースで
巡回し、Record { value, multiplier, unit, ... } リストを返します。
formatValue(record) :
- 整数 + multiplier=1 →
Long.toString(...) - Number →
value * multiplier(double) - その他 →
String.valueOf(value)
対応 / 非対応
- ✅ SND_NKE → REQ_UD2 → RSP_UD サイクル
- ✅ Primary addressing (1~250)
- ✅ Secondary addressing (slave selection + primary 253 read)
- ✅ Application Reset (CI=0x50)
- ✅ DIF/VIF data record パース + multiplier スケール
- ❌ FCB (frame count bit) toggle / Multi-frame UD2
- ❌ Wireless M-Bus (EN 13757-4)
- ❌ Encryption (mode 5 / 7 — スマートメータ)
テストカバレッジ
test/java/plantpulse/driver/protocol/mbus/
| クラス | テスト数 |
|---|---|
MBusAckTest | 4 |
MBusBcdTest | 13 |
MBusChecksumTest | 4 |
MBusDataRecordTest | 7 |
MBusDriverAddressTest | 10 |
MBusDriverWriteTest | 9 |
MBusFrameTest | 14 |
MBusSpecExtraTest | 28 |
計 89 テスト。
参考
- EN 13757-2 Physical and link layer
- EN 13757-3 Application layer / DIF/VIF / Secondary addressing
- コード:
src/plantpulse/driver/protocol/mbus/