Zum Hauptinhalt springen

M-Bus Treiber

Übersicht

Eigene native Java-Implementierung von M-Bus (Meter-Bus, EN 13757-2/3). Die Anbindung erfolgt per TCP-Socket an ein in der Praxis übliches Wired-M-Bus-Master-Gateway oder an einen Seriell-TCP-Konverter (Moxa NPort, USR-TCP232 usw.), um standardkonforme M-Bus-Frames zu senden und zu empfangen.

PunktWert
opc_typeMBUS
Implementierungsklasseplantpulse.driver.protocol.mbus.MBusDriver
Bibliothek(keine — Eigenimplementierung. EN 13757-2/3)
readgut (REQ_UD2 → RSP_UD)
writegut (Slave Selection / Application Reset)
Standardport10001 (Moxa NPort Standard)
Sicherheitkeine

Klassen / Struktur

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() :

  1. TCP-Verbindung (host:10001).
  2. SND_NKE (Short Frame, C=0x40, A=default-address) senden.
  3. Empfang von ACK (0xE5) prüfen — auch ohne Antwort gilt connected=true (je nach Gateway unterschiedlich).

Zusammenfassung des Wire-Formats

Short Frame (SND_NKE / ACK auf Slave Selection)

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
BefehlCCIBedeutung
SND_NKE0x40Initialize slave
REQ_UD20x5BUser-Data-Anforderung
Slave Selection0x530x52Secondary addressing
App Reset0x530x50Application reset

OPC-Registrierungsoptionen (options)

SchlüsselBedeutungStandard
default-addressprimary address (1~250)1
connect-timeoutms3000
read-timeoutms3000

Tag-Adressformat

Primary addressing

NotationBedeutung
1:0primary 1, erster Record
5:2primary 5, dritter Record
1primary 1, gesamte User-Data als Hex

Secondary addressing

NotationBedeutung
secondary:12345678AB1C010716 Hex-Zeichen (ID 4 + Mfg 2 + Ver 1 + Med 1)
secondary:<16-hex>:<recordIndex>wie oben + Record-Index
select:12345678:43932:1:7dezimaler Alias (id, mfg, ver, med)
select:12345678:43932:1:7:0+ Record-Index

trySecondaryAddress() sendet zuerst die Secondary Slave Selection → anschließend REQ_UD2 mit primary=253. Die ID wird im Wire-Format nach EN 13757-3 als LSB-first BCD codiert (MBusBcd.encodeIdToBcd4).

write-Adressformat

NotationVerhalten
secondary:<hex> / select:<id>:<mfg>:<ver>:<med>nur Slave Selection senden
app-reset:<subcode>Application Reset an primary=default-address
app-reset:<primary>:<subcode>primary explizit angegeben
select-and-reset:<id>:<mfg>:<ver>:<med>:<subcode>Reset nach Secondary-Auswahl

Der subcode kann auch als address.value übergeben werden.


Record-Decodierung

MBusDataRecord.parseAll(userData, off=12, len) durchläuft die User-Data (ab Byte 12 nach dem Header) auf Basis von DIF/VIF und liefert eine Record { value, multiplier, unit, ... }-Liste zurück.

formatValue(record) :

  • Ganzzahl + multiplier=1 → Long.toString(...)
  • Number → value * multiplier (double)
  • sonstige → String.valueOf(value)

Unterstützt / nicht unterstützt

  • ✅ Zyklus SND_NKE → REQ_UD2 → RSP_UD
  • ✅ Primary addressing (1~250)
  • ✅ Secondary addressing (Slave Selection + Read mit primary 253)
  • ✅ Application Reset (CI=0x50)
  • ✅ Parsing von DIF/VIF-Data-Records + Multiplier-Skalierung
  • ❌ FCB (frame count bit) Toggle / Multi-Frame UD2
  • ❌ Wireless M-Bus (EN 13757-4)
  • ❌ Verschlüsselung (Mode 5 / 7 — Smart Meter)

Testabdeckung

test/java/plantpulse/driver/protocol/mbus/

KlasseAnzahl Tests
MBusAckTest4
MBusBcdTest13
MBusChecksumTest4
MBusDataRecordTest7
MBusDriverAddressTest10
MBusDriverWriteTest9
MBusFrameTest14
MBusSpecExtraTest28

Insgesamt 89 Tests.


Referenzen

  • EN 13757-2 Physical and link layer
  • EN 13757-3 Application layer / DIF/VIF / Secondary addressing
  • Code: src/plantpulse/driver/protocol/mbus/