# wmbusmeters The program acquires utility meter readings from wired m-bus or wireless wm-bus meters. The readings can then be published using MQTT, curled to a REST api, inserted into a database or stored in a log file. # What does it do? Wmbusmeters converts incoming telegrams from (w)mbus/OMS compatible meters like: `1844AE4C4455223368077A55000000_041389E20100023B0000` into human readable: `MyTapWater 33225544 123.529 m³ 0 m³/h 2024-03-03 19:36:22` or into csv: `MyTapWater;33225544;123.529;0;2024-03-03 19:36:45` or into json: ```json { "media":"water", "meter":"iperl", "name":"MyTapWater", "id":"33225544", "max_flow_m3h":0, "total_m3":123.529, "timestamp":"2024-03-03T18:37:00Z" } ``` Wmbusmeters can collect telegrams from radio using hardware dongles or rtl-sdr software radio dongles, or from m-bus meters using serial ports, or from files/pipes. [FAQ/WIKI/MANUAL pages](https://wmbusmeters.github.io/wmbusmeters-wiki/) The program runs on GNU/Linux, MacOSX, FreeBSD, and Raspberry Pi. | System | Status | | ------------ |:-------------:| | Ubuntu | [![Build Ubuntu Status](https://github.com/wmbusmeters/wmbusmeters/workflows/Build%20Ubuntu/badge.svg)](https://github.com/wmbusmeters/wmbusmeters/actions)| | MacOSX | [![Build MacOSX Status](https://github.com/wmbusmeters/wmbusmeters/workflows/Build%20MacOSX/badge.svg)](https://github.com/wmbusmeters/wmbusmeters/actions)| | Docker | [![Build Docker Status](https://github.com/wmbusmeters/wmbusmeters/workflows/Build%20docker/badge.svg)](https://hub.docker.com/r/wmbusmeters/wmbusmeters/)| | Snap | [![Build Snap Status](https://github.com/wmbusmeters/wmbusmeters/workflows/Build%20Snap/badge.svg)](https://snapcraft.io/wmbusmeters)| # Distributions **wmbusmeters** package is available on [Fedora](https://src.fedoraproject.org/rpms/wmbusmeters) _(version 31 or newer)_ and can be simply installed by using: ```shell dnf install wmbusmeters ``` Availability of **wmbusmeters** for other Linux distributions can be checked on [release-monitoring](https://release-monitoring.org/project/88654/) project page. # Docker Experimental docker containers are available here: https://hub.docker.com/r/wmbusmeters/wmbusmeters # Snap Experimental snaps are available here: https://snapcraft.io/wmbusmeters Read the wiki for more info on how to use the snap: https://wmbusmeters.github.io/wmbusmeters-wiki/SNAP.html # Build from source and run as a daemon Building and installing from source is easy and recommended since the development progresses quickly. First remove the wmbus dongle (im871a,amb8465(metis),amb3665,cul,rc1180) or the generic rtlsdr dongle (RTL2832U) from your computer. Then do: `./configure; make; sudo make install` will install wmbusmeters as a daemon. # Usage Check the contents of your `/etc/wmbusmeters.conf` file, assuming it has `device=auto:t1` and you are using a im871a,amb8465(metis),amb3665,rc1180,cul or rtlsdr device, then you can now start the daemon with `sudo systemctl start wmbusmeters` or you can try it from the command line `wmbusmeters auto:t1` Wmbusmeters will scan for wmbus devices every few seconds and detect whenever a device is plugged in or removed. However since wmbusmeters now supports several dongle types, the scan can take some time! Use `auto` for testing and to find your dongle. For production it is very much recommended that you change `auto:t1` to the device name with the full device path (eg `/dev/ttyUSB0:im871a:c1,t1`). This will skip the slow probing for all possible wmbus dongles when wmbusmeters startup. If the serial device (ttyUSB0) might change you can also use `device=im871a:c1,t1` which will probe all serial devices but only scans for im871a which also speeds it up. Note that the rtl-sdr devices are not found under the tty devices (e.g. `/dev/tty...`). Instead the rtl-sdr devices are accessed through character device special files named `/dev/swradio0` to `/dev/swradio255`[^kernel_docs_sdr]. Wmbusmeters uses librtsldr to probe these devices. [^kernel_docs_sdr]: https://docs.kernel.org/userspace-api/media/v4l/dev-sdr.html?highlight=sdr#software-defined-radio-interface-sdr If you have to scan serial devices, then remember that some Raspberry PIs are upset when random data is sent to `/dev/ttyAMA0` when it is configured in bluetooth mode. To solve this, add `donotprobe=/dev/ttyAMA0` To have the wmbusmeters daemon start automatically when the computer boots do: `sudo systemctl enable wmbusmeters` You can trigger a reload of the config files with `sudo killall -HUP wmbusmetersd` (Note! make install only works for GNU/Linux. For MacOSX try to start `wmbusmetersd /tmp/thepidfile` from a script instead.) You can also start the daemon with another set of config files: `wmbusmetersd --useconfig=/home/me/.config/wmbusmeters /tmp/thepidfile` When using useconfig, the files/dir should be: `/home/me/.config/wmbusmeters/wmbusmeters.conf` and the meters dir: `/home/me/.config/wmbusmeters/wmbusmeters.d` Check the config file /etc/wmbusmeters.conf and edit the device. For example: `/dev/ttyUSB1:amb8465:c1,t1` or `im871a:c1,t1` or `im871a[457200101056]:t1`. Adding a device like auto or im871a will trigger an automatic probe of all serial ttys to auto find or to find on which tty the im871a resides. If you specify a full device path like `/dev/ttyUSB0:im871a:c1` or `rtlwmbus` or `rtl433` then it will not probe the serial devices. If you must be really sure that it will not probe something you can add `donotprobe=/dev/ttyUSB0` or `donotprobe=all`. You can specify combinations like: `device=rc1180:t1` `device=auto:c1` to set the rc1180 dongle to t1 but any other auto-detected dongle to c1. Some dongles have identifiers (im871a,amb8465(metis),amb3665 and rtlsdrs) (for example: rtlsdr can be set with `rtl_eeprom -s myname`) You might have two rtlsdr dongles, one attached to an antenna tuned to 433MHz and the other attached to an antenna tuned for 868.95MHz, then a more complicated setup could look like this: ``` device=rtlwmbus[555555]:433M device=rtlwmbus[112233] device=/dev/ttyUSB0:im871a[00102759]:c1,t1 device=/dev/ttyUSB1:rc1180:t1 ``` # Bus aliases and polling To poll an C2/T2/S2 wireless meter or an wired m-bus meter you need to give the (w)mbus device a bus-alias, for example here we pick the bus alias MAIN for the mbus using 2400 bps for all meters on this bus. ``` MAIN=/dev/ttyUSB0:mbus:2400 ``` and here we pick the bus alias RADIOMAIN for an im871a dongle: ``` RADIOMAIN=/dev/ttyUSB1:im871a:c2 ``` The bus alias is then used in the meter driver specification to specify which bus the mbus poll request should be sent to. ``` wmbusmeters --pollinterval=60s MAIN=/dev/ttyUSB0:mbus:2400 MyTempMeter piigth:MAIN:mbus 12001932 NOKEY ``` If you want to poll an mbus meter using the primary address, use p0 to p250 (deciman numbers) instead of the full 8 digit secondary address. ``` wmbusmeters --pollinterval=60s MAIN=/dev/ttyUSB0:mbus:2400 MyTempMeter piigth:MAIN:mbus p0 NOKEY ``` # Example wmbusmeter.conf file ```ini loglevel=normal # You can use auto:t1 to find the device you have connected to your system. # But do not use auto here since it will cause unnecessary and slow probing of the serial ports. device=/dev/ttyUSB0:im871a:c1,t1 # And mbus device=MAIN=/dev/ttyUSB1:mbus:2400 # But do not probe this serial tty. donotprobe=/dev/ttyACM2 logtelegrams=false format=json meterfiles=/var/lib/wmbusmeters/meter_readings meterfilesaction=overwrite meterfilesnaming=name meterfilestimestamp=day logfile=/var/log/wmbusmeters/wmbusmeters.log shell=/usr/bin/mosquitto_pub -h localhost -t wmbusmeters/$METER_ID -m "$METER_JSON" alarmshell=/usr/bin/mosquitto_pub -h localhost -t wmbusmeters_alarm -m "$ALARM_TYPE $ALARM_MESSAGE" alarmtimeout=1h alarmexpectedactivity=mon-sun(00-23) ignoreduplicates=true ``` Then add a meter file in /etc/wmbusmeters.d/MyTapWater ```ini name=MyTapWater id=12345678 key=00112233445566778899AABBCCDDEEFF driver=multical21 ``` And an mbus meter file in /etc/wmbusmeters.d/MyTempHygro ```ini name=MyTempHygro id=11223344 driver=piigth:MAIN:mbus pollinterval=60s ``` # Important information about meter drivers and their names. You can use `driver=auto` to have wmbusmeters automatically detect and use the best driver for your meter, but you should >not< use auto in production. You can find out which driver is recommended by running `wmbusmeters im871a:t1`. This will print information like: ``` Received telegram from: 71727374 manufacturer: (BMT) BMETERS, Italy (0x9b4) type: Heat/Cooling load meter (0x0d) encrypted ver: 0x0b driver: hydrocalm3 ``` For production use it is very much recommended that you specify the exact driver in the meter file. The reason is that new and better drivers might be developed for your meter, where the keys and the content of the json might change. Such new drivers are guaranteed to have a different driver name. The auto look up will change to the new driver, but the old driver will still work. So wmbusmeters strives to guarantee that if you have specified the driver name, then wmbusmeters can be safely upgraded at any time. The json will not change in an incompatible way. (The only allowed changes are: adding new fields and changing the ordering.) Now plugin your wmbus dongle. Wmbusmeters should start automatically, check with `tail -f /var/log/syslog` and `tail -f /var/log/wmbusmeters/wmbusmeters.log` (If you are using an rtlsdr dongle, then make sure that either the binaries `/usr/bin/rtl_sdr` and `/usr/bin/rtl_wmbus` exists and are executable. Or that the executable `rtl_sdr/rtl_wmbus` binaries exists inside the same directory as the wmbusmeters executable. If not you will see the error message `(rtlwmbus) error: when starting as daemon, wmbusmeters looked for .../rtl_wmbus and /usr/bin/rtl_wmbus, but found neither!` and the daemon will refuse to start.) The latest reading of the meter can also be found here: `/var/lib/wmbusmeters/meter_readings/MyTapWater` You can use several ids using `id=1111111,2222222,3333333` or you can listen to all meters of a certain type `id=*` or you can suffix with star `id=8765*` to match all meters with a given prefix. If you supply at least one positive match rule, then you can add filter out rules as well. For example `id=*,!2222*` which will match all meter ids, except those that begin with 2222. You can also specify the exact manufacturer, version and type: `id=11111111.M=KAM.V=1b.T=16` or a subset: `id=11111111.T=16` or all telegrams from 22222222 except those with version 77: `id=22222222,!22222222.V=77` You can also use the fully specified secondary address that is printed by libmbus after doing a bus scan, ie `100002842941011B` which is equivalent to `10000284.M=PII.V=01.T=1B` When matching all meters from the command line you can use `ANYID` instead of `*` to avoid shell quotes. # Add static and calculated fields to the output You can add the static json data `"address":"RoadenRd 456","city":"Stockholm"` to every json message with the wmbusmeters.conf setting: ```ini field_address=RoadenRd 456 field_city=Stockholm ``` If you add `field_floor=5` to the meter file `MyTapWater`, then you can have the meter tailored static json `"floor":"5"` added to telegrams handled by that particular meter. (The old prefix json_ still works.) You can add unit conversions and calculated values to the meter files using `calculate_...`. The formulas track units. If the unit do not match up, then the formula will generate a null value. When two units are compatible it will automatically convert the value between two units. The formula ```ini calculate_sum_mj=5 kwh + 8 gj + (7 kw * 3 h) ``` will add the field: ```json "sum_mj":8093.6 ``` Units inside the formula calculation are tracked as arbitrary SI unit exponents (ie Volt is `1kgm²s⁻³a⁻¹`) however the final result must be a named unit (ie the calculated field must end with `_v`). The existing named units can be found with `wmbusmeters --listunits`. If you make a mistake in the formula you will get a warning: ``` Warning! Ignoring calculated field sum because parse failed: Cannot add [kw|Power|1000kgm²s⁻³] to [gj|Energy|1×10⁹kgm²s⁻²]! 5 kw + 8 gj + (7 kw * 3 h) ^~~~~ ``` You need parentheses in the formulas since operator precedence is not yet implemented. ```ini calculate_total_l=total_m3 calculate_approx_power_m3ch=(t1_temperature_c-t2_temperature_c)*volume_flow_m3h calculate_total_mj=total_energy_consumption_kwh ``` ``` wmbusmeters --format=json --ppjson --field_collector=cm57829 --calculate_total_l=total_volume_m3 --calculate_approx_power_m3ch='(t1_temperature_c-t2_temperature_c)*volume_flow_m3h' --calculate_total_mj=total_energy_consumption_kwh 5e442d2c1155775540047a7d0050252f2f0406c50e000004147B86000004ff074254000004ff086047000002594117025d9a14023Bed0302ff220000026cca2c4406750B00004414ad680000426cc12c2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f Heato kamheat 55775511 NOKEY ``` which will output: ```json { "media":"heat", "meter":"kamheat", "name":"Heato", "id":"55775511", "status":"OK", "total_energy_consumption_kwh":3781, "total_volume_m3":344.27, "volume_flow_m3h":1.005, "t1_temperature_c":59.53, "t2_temperature_c":52.74, "forward_energy_m3c":21570, "return_energy_m3c":18272, "meter_date":"2022-12-10", "target_energy_kwh":2933, "target_volume_m3":267.97, "target_date":"2022-12-01", "total_l":344270, "approx_power_m3ch":6.82395, "total_mj":13611.6, "timestamp":"2023-01-14T07:20:22Z", "collector":"cm57829" } ``` If you have connected your Lansen pulse counting meter to an electricity meter triggering a pulse per 0.1 kwh, then you can directly calculate a value based on the counters: ``` wmbusmeters --format=json --ppjson --calculate_total_kwh='1000 kwh + (a_counter * 0.1 kwh)' 234433300602010014007a8e0400002f2f0efd3a1147000000008e40fd3a341200000000 Electricity lansenpu 00010206 NOKEY ``` ```json { "media":"other", "meter":"lansenpu", "name":"Electricity", "id":"00010206", "status":"POWER_LOW", "a_counter":4711, "b_counter":1234, "total_kwh":1471.1, "timestamp":"2023-01-14T07:25:34Z" } ``` # Miscellaneous If you are running on a Raspberry PI with flash storage and you relay the data to another computer using a shell command (`mosquitto_pub` or `curl` or similar) then you might want to remove `meterfiles` and `meterfilesaction` to minimize the writes to the local flash file system. Also when using the Raspberry PI it can get confused by the serial ports, in particular the bluetooth port might come and go as a serial tty depending on the config. Therefore it can be advantageous to use the auto device to find the proper tty (eg /dev/ttyUSB0) and then specify this tty device explicitly in the config file, instead of using auto. This assumes that you only have a single usb dongle otherwise the USB tty names can change depending on how and when the devices are unplugged/replugged and the pi restarted. If you have multiple devies with different antennas, then you should instead use donotprobe to avoid the ttys that can never have a wmbus dongle. If you specify `--meterfilesaction=append --meterfilestimestamp=day` then wmbusmeters will append all todays received telegrams in for example the file `Water_2019-12-11`, the day after the telegrams will be recorded in `Water_2019-12-12`. You can change the resolution to day,hour,minute and micros. Micros means that every telegram gets their own file. The purpose of the alarm shell and timeout is to notify you about problems within wmbusmeters and the wmbus dongles, not the meters themselves. Thus the timeout is for a dongle to receive some telegram at all. It does not matter from which meter. # Run using config files If you cannot install as a daemon, then you can also start wmbusmeters in your terminal using the config files in `/etc/wmbusmeters`. ```shell wmbusmeters --useconfig=/etc ``` Or you can start wmbusmeters with your own config files: ```shell wmbusmeters --useconfig=/home/me/.config/wmbusmeters ``` If you already have config with a device specified, and you want to use the config with another device. You might have multiple meters in the config that you want to listen to. Then you can add `--overridedevice` to override the settings in the config. Like this: ```shell wmbusmeters --useconfig=/home/me/.config/wmbusmeters --overridedevice=rtlwmbus ``` You must have both `--useconfig=` and `--overridedevice=` for it to work. The files/dir should then be located here: `/home/me/.config/wmbusmeters/wmbusmeters.conf` and `/home/me/.config/wmbusmeters/wmbusmeters.d` The option `--useconfig=` can only be combined with a few other options: `--overridedevice= --listento= --exitafter= --oneshot= --silent --normal --verbose --debug --trace` When running using config files then you can trigger a reload of the config files using `sudo killall -HUP wmbusmetersd` or `killall -HUP wmbusmeters` depending on if you are running as a daemon or not. # Running without config files, good for experimentation and test. ``` wmbusmeters version: 1.15.0 Usage: wmbusmeters {options} [device] { [meter_name] [meter_driver] [meter_id] [meter_key] }* wmbusmeters {options} [hex] { [meter_name] [meter_driver] [meter_id] [meter_key] }* wmbusmetersd {options} [pid_file] As {options} you can use: --alarmexpectedactivity=mon-fri(08-17),sat-sun(09-12) Specify when the timeout is tested, default is mon-sun(00-23) --alarmshell= invokes cmdline when an alarm triggers --alarmtimeout=