Skip to main content

Meter-Bus for Python

Build status codecov pypi GitHub issues GitHub issues PyPI Status

About

M-Bus (Meter-Bus) is a European standard (EN 13757-2 physical and link layer, EN 13757-3 application layer) for the remote reading of gas or electricity meters. M-Bus is also usable for other types of consumption meters. The M-Bus interface is made for communication on two wires, making it very cost-effective.

Python version

I've decided only to support active Python version. Thus, any EOL version is not supported.

Current State (2025)

I’m still active, but as with most side projects, this one often takes a back seat.

If you have improvements that could benefit the project, feel free to submit a pull request. If it’s a good fit, I’ll be happy to merge it.

Current State (2022)

The library works, but it lacks proper documentation. Well, it lacks any documentation, to be honest.

The implementation is currently under heavy development. Its original intended use case was particular, as a library to aid in decoding M-Bus telegrams sent over HTTP, and might thus not suit everyone.

Still, it is a generic library and supports several different use cases.

  • Decoding of re-encoded M-Bus frames sent from an Elvaco Wireless M-Bus master over HTTP.
  • Communicating with M-Bus devices over RS-232 serial.
  • Communication with M-Bus devices over RFC 2217.
  • As a debugging tool to decode M-Bus frames.

Currently, only the variable data structures are implemented. The library can only decode M-Bus frames. It does presently NOT support encoding and transmission of M-Bus frames, such as control frames.

However, if the need arises, I might implement missing pieces on a request basis.

Tools

You can find a set of utilities in the tools folder.

  • mbus-serial-request-data.py
  • mbus-serial-request-data-multi-reply.py
  • mbus-serial-scan.py
  • mbus-serial-scan-secondary.py

These tools can communicate over a serial device /dev/ttyX or even over RFC2217 using the format rfc2217://host:port.

Suppose you are using ser2net as an RFC2217 server. You need to configure it the following way:

2000:telnet:0:/dev/ttySX:2400 remctl banner

Known Issues

  • Missing: Fixed data structure parsing.
  • Missing: Encoding to M-Bus frames.
  • Missing: Slave configuration.
  • Missing: Extended VIF codes.

What works

  • Querying an M-Bus device over serial.
  • Parsing of a complete telegram.
  • Parsing of just the Used Data segment.
  • Generating a basic JSON structure from the telegram/user-data/records.

Basic API documentation

meterbus.load(data)

  • data[str]: M-Bus frame data

Returns an object of either type WTelegramSndNr, TelegramACK, TelegramShort, TelegramControl or TelegramLong. If an error occurs, it will raise an MBusFrameDecodeError.

meterbus.debug(state)

  • state[bool]: set the global debug state

Produces debug messages to stdout.

meterbus.send_ping_frame(ser, address)

  • ser[pySerial connection]: an open pySerial object
  • address: The target's primary address

Sends a PING frame to address over the serial connection ser.

meterbus.recv_frame(ser, length)

  • ser[pySerial connection]: an open pySerial object
  • length: The minimum length of the reply. An ACK frame is one (1) byte.

Reads an entire frame and returns the unparsed data.

meterbus.send_request_frame_multi(ser, address, req)

  • ser[pySerial connection]: an open pySerial object
  • address: The target's primary address

If req is None, build a new request frame using address and send it.

meterbus.send_select_frame(ser, secondary_address)

  • ser[pySerial connection]: an open pySerial object
  • secondary_address[str]: A target using secondary address format

Sends a select frame with the supplied secondary address.

meterbus.XXX

More to come...

Code examples

Decode the value of a single record (record 3)

#!/usr/bin/env python3

import meterbus

data = "\x68\x6A\x6A\x68\x08\x01\x72\x43\x53\x93\x07\x65" \
       "\x32\x10\x04\xCA\x00\x00\x00\x0C\x05\x14\x00\x00" \
       "\x00\x0C\x13\x13\x20\x00\x00\x0B\x22\x01\x24\x03" \
       "\x04\x6D\x12\x0B\xD3\x12\x32\x6C\x00\x00\x0C\x78" \
       "\x43\x53\x93\x07\x06\xFD\x0C\xF2\x03\x01\x00\xF6" \
       "\x01\x0D\xFD\x0B\x05\x31\x32\x4D\x46\x57\x01\xFD" \
       "\x0E\x00\x4C\x05\x14\x00\x00\x00\x4C\x13\x13\x20" \
       "\x00\x00\x42\x6C\xBF\x1C\x0F\x37\xFD\x17\x00\x00" \
       "\x00\x00\x00\x00\x00\x00\x02\x7A\x25\x00\x02\x78" \
       "\x25\x00\x3A\x16"

telegram = meterbus.load(data)
print telegram.records[3].parsed_value
~$ 2014-02-19T11:18

Request a frame over Serial and dump it in JSON format

#!/usr/bin/env python3

import serial
import meterbus

address = 254

with serial.Serial('/dev/ttyACM0', 2400, 8, 'E', 1, 0.5) as ser:
  meterbus.send_ping_frame(ser, address)
  frame = meterbus.load(meterbus.recv_frame(ser, 1))
  assert isinstance(frame, meterbus.TelegramACK)

  meterbus.send_request_frame(ser, address)
  frame = meterbus.load(meterbus.recv_frame(ser, meterbus.FRAME_DATA_LENGTH))
  assert isinstance(frame, meterbus.TelegramLong)

  print(frame.to_JSON())

M-Bus Packet Format

Single Character Short Frame Control Frame Long Frame
E5h Start 10h Start 68h Start 68h
C Field L Field = 3 L Field
A Field L Field = 3 L Field
Check Sum Start 68h Start 68h
Stop 16h C Field C Field
A Field A Field
CI Field CI Field
Check Sum User Data (0-252 Byte)
Stop 16h Check Sum
Stop 16h

License

Please see the LICENSE file

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pymeterbus-0.8.5.tar.gz (40.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pymeterbus-0.8.5-py3-none-any.whl (36.8 kB view details)

Uploaded Python 3

File details

Details for the file pymeterbus-0.8.5.tar.gz.

File metadata

  • Download URL: pymeterbus-0.8.5.tar.gz
  • Upload date:
  • Size: 40.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.5

File hashes

Hashes for pymeterbus-0.8.5.tar.gz
Algorithm Hash digest
SHA256 7ca339b45a1f8db4571d2f7df8de8c5d580844c2ff9eabe22efd6b8ae4aa27a4
MD5 753e45e46dba91f62631c5152fdb925f
BLAKE2b-256 fdb60f3557ac42c490191e561e00dfa8039050c2e89200872423c9b7a66b3819

See more details on using hashes here.

File details

Details for the file pymeterbus-0.8.5-py3-none-any.whl.

File metadata

  • Download URL: pymeterbus-0.8.5-py3-none-any.whl
  • Upload date:
  • Size: 36.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.5

File hashes

Hashes for pymeterbus-0.8.5-py3-none-any.whl
Algorithm Hash digest
SHA256 d8c913ff43a736c53a374d6bdc8944f8c9be2928d72a46583da4cca8c18f2eb0
MD5 56e1e3844416c21fbd0e4221c8ff8477
BLAKE2b-256 252ae64a58962e5767cf2d2c9a8ea59e0c081f97be887f4d0ea5493549f03da9

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.8.5 This release

2 files

0.8.4

2 files

0.8.3

2 files

0.8.2

2 files

0.8.1

2 files

0.8.0

2 files

0.7.17

2 files

0.7.15

2 files

0.7.14

2 files

0.7.13

2 files

0.7.12

2 files

0.7.11

1 file

0.7.10

1 file

0.7.8

1 file

0.7.0

3 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page