m-bus-parser
For contributing see CONTRIBUTING.md, for change history see CHANGELOG.md.
An open-source parser (decoder/deserializer) for the wired and wireless M-Bus protocol, written in Rust.
M-Bus (Meter-Bus) is a European standard (EN 13757-2 physical and link layer, EN 13757-3 application layer) for remote reading of water, gas, electricity, and heat meters. — Wikipedia
- Try it live: maebli.github.io/m-bus-parser
- Spec: m-bus.com/documentation · OMS specification
Features
- Parses wired M-Bus (EN 13757-2/-3) and wireless M-Bus (wMBus) frames
- Five output formats:
table,json,yaml,csv,mermaid - AES-128 decryption for encrypted wMBus frames (mode 5 / mode 7)
no_stdcompatible — runs on embedded targets (manufacturer lookup and output formats requirestd)- Available as a Rust library, CLI, WebAssembly (npm) and Python bindings
Deployments
Web app (WebAssembly)
Paste a hex frame at maebli.github.io/m-bus-parser and get instant output in any format, including a rendered Mermaid diagram. Frames can be shared via URL.
Source: wasm/
CLI
Source: cli/
Python bindings
Source: python/
CLI Usage
m-bus-parser-cli parse [OPTIONS]
Options:
-d, --data <DATA> Raw M-Bus frame as a hex string
-f, --file <FILE> File containing a hex frame
-t, --format <FORMAT> Output format: table (default), json, yaml, csv, mermaid
-k, --key <KEY> AES-128 decryption key (32 hex characters)
Input hex can be in any of these forms:
68 3D 3D 68 ... (space-separated)
683D3D68... (plain hex)
0x68,0x3D,0x3D,... (0x-prefixed, comma-separated)
Table output (default)
Long Frame
┌────────────────────────────────┬─────────────┐
│ Function │ Address │
├────────────────────────────────┼─────────────┤
│ RspUd (ACD: false, DFC: false) │ Primary (1) │
└────────────────────────────────┴─────────────┘
┌───────────────────────┬──────────────────────────────────────────┐
│ Field │ Value │
├───────────────────────┼──────────────────────────────────────────┤
│ Identification Number │ 02205100 │
├───────────────────────┼──────────────────────────────────────────┤
│ Manufacturer │ SLB │
├───────────────────────┼──────────────────────────────────────────┤
│ Manufacturer Name │ Schlumberger Industries │
├───────────────────────┼──────────────────────────────────────────┤
│ Website │ slb.com │
├───────────────────────┼──────────────────────────────────────────┤
│ Description │ Energy and water metering │
├───────────────────────┼──────────────────────────────────────────┤
│ Access Number │ 0 │
├───────────────────────┼──────────────────────────────────────────┤
│ Status │ Permanent error, Manufacturer specific 3 │
├───────────────────────┼──────────────────────────────────────────┤
│ Security Mode │ No encryption used │
├───────────────────────┼──────────────────────────────────────────┤
│ Version │ 2 │
├───────────────────────┼──────────────────────────────────────────┤
│ DeviceType │ Heat Meter (Return) │
└───────────────────────┴──────────────────────────────────────────┘
┌─────────────────────────────────────────┬───────────────────────┬────────────┬─────────────┐
│ Value │ Data Information │ Header Hex │ Data Hex │
├─────────────────────────────────────────┼───────────────────────┼────────────┼─────────────┤
│ (0)e4[Wh] │ 0,Inst,32-bit Integer │ 04 07 │ 00 00 00 00 │
├─────────────────────────────────────────┼───────────────────────┼────────────┼─────────────┤
│ (3)e-1[m³](Volume) │ 0,Inst,BCD 8-digit │ 0C 15 │ 03 00 00 00 │
├─────────────────────────────────────────┼───────────────────────┼────────────┼─────────────┤
│ (1288)e-1[°C] │ 0,Inst,BCD 4-digit │ 0A 5A │ 88 12 │
└─────────────────────────────────────────┴───────────────────────┴────────────┴─────────────┘
Other formats
# JSON
# YAML
# CSV
# Mermaid diagram source (renders in the web app)
# With AES-128 decryption key
Library Usage
Add to Cargo.toml:
[]
= "0.1"
Parse a wired frame
use ;
use MbusData;
use ;
let frame_bytes: = vec!;
let frame = try_from?;
if let LongFrame = frame
Serialize to any format
use serialize_mbus_data;
let hex = "68 3D 3D 68 08 01 72 ...";
let table = serialize_mbus_data;
let json = serialize_mbus_data;
let yaml = serialize_mbus_data;
let csv = serialize_mbus_data;
let mermaid = serialize_mbus_data;
// With decryption key
let key: = ;
let decrypted = serialize_mbus_data;
no_std usage
The core parsing types are no_std compatible. Disable default features:
[]
= { = "0.1", = false }
An embedded example (Cortex-M) is in examples/cortex-m/.
Output Formats
| Format | Flag | Description |
|---|---|---|
table |
default | Human-readable ASCII table |
json |
-t json |
JSON |
yaml |
-t yaml |
YAML |
csv |
-t csv |
Comma-separated values |
mermaid |
-t mermaid |
Mermaid flowchart source (renders in web app) |
Protocol Coverage
Frame types
| Type | CI bytes | Status |
|---|---|---|
| Long frame | 0x72, 0x76, 0x7A | Supported |
| Short frame | — | Supported |
| Control frame | — | Supported |
| Single character | — | Supported |
| Wireless frame | wMBus link layer | Supported |
CI field types
Implemented
ResponseWithVariableDataStructure(CI: 0x72, 0x76, 0x7A)ResponseWithFixedDataStructure(CI: 0x73)ApplicationLayerShortTransport(CI: 0x7D)ApplicationLayerLongTransport(CI: 0x7E)ExtendedLinkLayerI(CI: 0x8A)ResetAtApplicationLevel
Not yet implemented
Returns ApplicationLayerError::Unimplemented for: SendData, SelectSlave, SynchronizeSlave, baud-rate commands, ExtendedLinkLayerII/III, COSEM/OBIS data, and various transport/network layer types.
Most common value information unit codes are supported. Contributions for additional CI types and VIF codes are welcome.
Frame Structure
Wireless Link Layer

Wired Link Layer (Long Frame)

Application Layer

Value Information Block

Related Projects
| Language | Project |
|---|---|
| C | libmbus by rscada |
| Java | jMbus |
| C# | Valley.Net.Protocols.MeterBus |
| JS | tmbus |
| Python | pyMeterBus |
