Disclaimer: This tool was mainly written to suffice my needs, which are: reading my two wired M-Bus water meters and send it to Home Assistant. I know there are many things which can be improved, but it's working good enough for me and someone else can try to use it as well.
Software is published 'as-is' without any guarantees.
- Reading M-Bus devices via 'TTL to M-Bus' converter
- Automatic discovery of connected M-Bus meters
- Publishing data to MQTT
- Optional Home Assistant MQTT Discovery compliance:
- automatic device and entity creation and update
- device unavailability reporting
- Template system to support different M-Bus devices
- TTL to M-Bus Master, like this one
- Raspberry Pi or anything with UART (USB-TTL converter should work as well, but have not tested)
- Linux (tested on Raspbian 12)
- libmbus
- python3 (tested on version 3.11)
-
Clone this git repo and enter the directory:
git clone https://github.com/nilvanis/libmbus2mqtt cd libmbus2mqtt
-
Create virtual environment and activate it:
python3 -m venv .venv source .venv/bin/activate
-
Install required libraries:
python3 -m pip install -r requirements.txt
-
Install libmbus
(you can check here for an example installation method) -
Prepare config.yaml
cp template_config.yaml config.yaml nano config.yaml
Change settings to reflect your setup. More info here.
Save file and exit (Ctrl+O, Ctrl+X).
In case you use HA MQTT Discovery, check if your meter is on the supported devices list.
If not, you must prepare a valid device template.
Templates are stored as json files in libmbus2mqtt/data/homeassistant_mappings
.
To match a proper template, libmbus2mqtt uses definitions from index.json
file.
Each entry syntax in index.json
is as follows:
"<TEMPLATE_FILENAME.json>": {
"Manufacturer": "ASDX",
"ProductName": "Super Water Meter"
}
For matching, you can use any field from <SlaveInformation>
libmbus xml output.
Device template JSON file syntax is as follows:
{
"0": {
"name": "Fabrication Number",
"icon": "mdi:numeric",
"platform": "sensor",
"value_template":"{{ value_json.fabrication_number }}",
"entity_category": "diagnostic"
},
"1": {
name, icon, platform, etc...
},
"2": {
name, icon, platform, etc...
},
<...>
"custom-xxx": {
name, icon, platform, etc...
}
}
0
, 1
, etc. are section numbers defined as id
number in <DataRecord id>
from libmbus xml output.
You must identify which section holds what information and based on that create a template.
Or you can just have generic sensors for everything.
'custom-xxx' are custom sensor you can publish.
Every custom sensor JSON section name must be preceded with `custom-'. All section names must be unique.
Since custom sensors does not have it's own DataRecord in libmbus xml output, value must be derived from other data.
Common use case is creating dedicated sensors from data in Manufacturer Specific field value.
If you need help, raise an issue and paste there your libmbus xml output, and I'll try to add a new template for you.
To start libmbus2mqtt, simply run:
python3 main.py
First, configuration will be loaded, libmbus path checked and then M-Bus will be scanned for available devices.
All found devices data will be published to MQTT.
You can run libmbus2mqtt as a service in the background and instruct the system to load it every time system boots.
In order to do that, create a new service file:
sudo nano /etc/systemd/system/libmbus2mqtt.service
Paste there:
[Unit]
Description=libmbus2mqtt
After=multi-user.target
[Service]
Type=simple
Restart=always
ExecStart=/home/user/libmbus2mqtt/.venv/bin/python3 /home/user/libmbus2mqtt/main.py
[Install]
WantedBy=multi-user.target
Where /home/user/libmbus2mqtt/
is your actual libmus2mqtt location.
Save the file and exit (Ctrl+O, Ctrl+X).
Now enable and run the service:
sudo systemctl enable libmbus2mqtt.service
sudo systemctl start libmbus2mqtt.service
poll_interval: 60 # [in seconds] How often M-Bus devices will be polled
mqtt:
host: example.com # IP address or FQDN of your MQTT server (or Home Assistant if you use 'Mosquitto broker' add-on)
port: 1883 # Port of the MQTT broker, by default 1883
username: user
password: pass
base_topic: libmbus2mqtt # Base topic under which devices info will be published
#custom_topic: example/devices/ # Setting this overrides base_topic and disables homeassistant section
interface:
libmbus_path: /usr/local/bin/ # Path where libmbus libraries are available
baudrate: 2400
serial_device: /dev/ttyAMA0 # Path where M-Bus Master is available via serial
homeassistant:
autodiscovery: True # Enable Home Assistant MQTT Discovery format for data publishing
discovery_prefix: homeassistant # Home Assistant MQTT Discovery prefix. By default: homeassistant
To test your libmbus installation, try below commands:
/usr/local/bin/mbus-serial-scan -b 2400 /dev/ttyAMA0
Where -b
is your M-Bus baudrate and /dev/ttyAMA0
is your serial device.
Expected output should be similar to this:
Found a M-Bus device at address 1
Next, poll an M-Bus device:
/usr/local/bin/mbus-serial-request-data -b 2400 /dev/ttyAMA0 1
where 1
is the discovered device address.
You should get a response similar to this:
<MBusData>
<SlaveInformation>
<Id>123456789</Id>
<Manufacturer>ASDX</Manufacturer>
<Version>1</Version>
<ProductName>Super Water Meter</ProductName>
<Medium>Water</Medium>
<AccessNumber>123</AccessNumber>
<Status>11</Status>
<Signature>1111</Signature>
</SlaveInformation>
<DataRecord id="0">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Fabrication number</Unit>
<Value>0987654321</Value>
<Timestamp>2025-01-05T20:36:14Z</Timestamp>
</DataRecord>
<DataRecord id="1">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>cust. ID</Unit>
<Value> </Value>
<Timestamp>2025-01-05T20:36:14Z</Timestamp>
</DataRecord>
<DataRecord id="2">
<Function>Instantaneous value</Function>
<StorageNumber>0</StorageNumber>
<Unit>Time Point (time & date)</Unit>
<Value>2025-01-05T22:05:00</Value>
<Timestamp>2025-01-05T20:36:14Z</Timestamp>
</DataRecord>
(...and many more <DataRecord> depending on the device)
</MBusData>
Based on this output, you can identify each 'sensor' for Home Assistant, where by 'sensor' I mean each DataRecord.
<SlaveInformation>
holds general device information you will also find in the Home Assistant MQTT device section.
-
First, you need to enable UART. Skip if you already did that.
In the Raspberry PI CLI run:sudo raspi-config
Next, enable UART by going through the menu:
3 Interface Options
->Serial Port
-><No>
-><Yes>
-
Connect adapter to the Raspberry Pi (via 40-PIN GPIO):
First make sure all devices are disconnected from any power source!
You can verify the Raspberry Pi GPIO pin numbers hereRaspberry Pi TTL to MBUS PIN 02 (5V) TTLVCC PIN 04 (5V) VIN PIN 06 (GND) GND PIN 08 (TX) TXD PIN 10 (RX) RXD -
Power up Raspberry Pi. Serial device should be available at /dev/ttyAMA0
Data sheet: https://se.itron.com/o/commerce-media/accounts/-1/attachments/3809944
Data sheet: https://api.apator.com/uploads/oferta/woda-i-cieplo/systemy/przewodowy/apt-mbus-na/apt-mbus-na-1-catalogue.pdf