Skip to content
Stand with Ukraine flag

Smartico WM-LR

Smartico WM-LR

Smartico WM-LR

Smartico

Platform
ThingsBoard
Hardware Type
Sensors
Connectivity
LoRaWAN
Industry
Energy Management, Smart Cities, Smart Buildings
Use Case
Smart Energy, Smart Metering, Water Metering

Introduction

The Smartico WM-LR is a wireless M-Bus reader for remote data collection from gas, water, electricity, and heat meters using the wM-Bus protocol, with transmission via LoRaWAN networks. It also includes an input for wired connection to the digital interface of Kamstrup meters, which can additionally be used for pulse counting. The waterproof housing allows outdoor installation, and the compact design enables mounting in confined spaces using pipe or surface adapters. In this guide, four water meters are connected to the device.

This guide describes how to receive telemetry from the Smartico WM-LR over LoRaWAN using ChirpStack and a ThingsBoard MQTT integration, and visualize the data on a dashboard.

Prerequisites

Configure ChirpStack

Register the Smartico WM-LR in ChirpStack and verify the device is transmitting. The device should appear on the Applications page with its serial number (like 0000020).

The uplink data converter decodes the Base64-encoded payload from the WM-LR into ThingsBoard telemetry format. Readings from each connected meter arrive in separate packets. The existSerial array in the decoder must list the serial numbers of all meters connected to the device — for example, var existSerial=['66413314','65656691','66413313','66413315'];.

  1. Download uplink_wm_bus_reader.json.
  2. Go to Integrations center ⇾ Data converters and click + Add data converter > Import converter.
  3. Drag and drop the downloaded uplink_wmbus_reader.json file.
  4. Click Import.
/** Decoder **/
var payloadStr = decodeToString(payload);
var data = JSON.parse(payloadStr);
var deviceName = data.deviceName;
var deviceType = 'wM-Bus Reader';
var res = _base64ToArrayBuffer(data.data);
if (res.length < 9)
return null;
var existSerial = ['66413314','65656691','66413313','66413315'];
var serialNumber1 = null;
var serialNumber2 = null;
var serialNumber3 = null;
var serialNumber4 = null;
var serialNumber = GetWMBusSerial(res[1], res[2], res[3], res[4], existSerial);
var dateTime = GetCurrentDateTime();
var waterWMBusValue1 = null;
var waterWMBusValue2 = null;
var waterWMBusValue3 = null;
var waterWMBusValue4 = null;
GetWMBusMeterValue(res[7], res[8], res[9], res[10], serialNumber, existSerial);
var low_bat = GetFlagError(res[0], 1);
var motion_detect = GetFlagError(res[0], 2);
var magnet_detect = GetFlagError(res[0], 3);
var tamper_detect = GetFlagError(res[0], 4);
var power_on = GetFlagError(res[0], 5);
var power_bat = GetFlagError(res[0], 6);
var err_time = GetFlagError(res[0], 7);
var cfg_done = GetFlagError(res[0], 8);
var result = {
deviceName: deviceName,
deviceType: deviceType,
attributes: {
integrationName: metadata['integrationName'],
},
telemetry: {
REAL_TIME: dateTime,
SERIAL1: serialNumber1,
SERIAL2: serialNumber2,
SERIAL3: serialNumber3,
SERIAL4: serialNumber4,
WATER_WMBUS_VALUE1: waterWMBusValue1,
WATER_WMBUS_VALUE2: waterWMBusValue2,
WATER_WMBUS_VALUE3: waterWMBusValue3,
WATER_WMBUS_VALUE4: waterWMBusValue4,
FLG_LOW_BAT: low_bat,
FLG_MOTION_DETECT: motion_detect,
FLG_MAGNET_DETECT: magnet_detect,
FLG_TAMPER_DETECT: tamper_detect,
FLG_POWER_ON: power_on,
FLG_POWER_BAT: power_bat,
FLG_ERR_TIME: err_time,
FLG_CFG_DONE: cfg_done
}
};
/** Helper functions **/
function decodeToString(payload) {
return String.fromCharCode.apply(String, payload);
}
function decodeToJson(payload) {
var str = decodeToString(payload);
return JSON.parse(str);
}
function GetCurrentDateTime(){
var a = new Date();
var year = a.getFullYear().toString();
var month = (a.getMonth()+1).toString();
if(month.length==1) month="0"+month;
var date = a.getDate().toString();
if(date.length==1) date="0"+date;
var hour = a.getHours().toString();
if(hour.length==1) hour="0"+hour;
var min = a.getMinutes().toString();
if(min.length==1) min="0"+min;
var sec = a.getSeconds().toString();
if(sec.length==1) sec="0"+sec;
return date + '.' + month + '.' + year + ' ' + hour + ':' + min + ':' + sec;
}
function _base64ToArrayBuffer(base64) {
var binary_string = atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
return bytes;
}
function GetWMBusSerial(byte1, byte2, byte3, byte4, arrSerial) {
var value1 = parseInt(byte1, 10).toString(2);
while(value1.length<8){value1='0'+value1;}
var value2 = parseInt(byte2, 10).toString(2);
while(value2.length<8){value2='0'+value2;}
var value3 = parseInt(byte3, 10).toString(2);
while(value3.length<8){value3='0'+value3;}
var value4 = parseInt(byte4, 10).toString(2);
while(value4.length<8){value4='0'+value4;}
var value = value1[4]+value1[5]+value1[6]+value1[7] + value2 + value3 + value4;
var res = parseInt(value,2).toString();
for (k = 0; k < arrSerial.length; k++) {
if (arrSerial[k] == res) {
if (k % 4 == 0) serialNumber1 = res;
if (k % 4 == 1) serialNumber2 = res;
if (k % 4 == 2) serialNumber3 = res;
if (k % 4 == 3) serialNumber4 = res;
return res;
}
}
return null;
}
function GetWMBusMeterValue(byte1, byte2, byte3, byte4, realSerialN, arrSerial) {
var value1 = parseInt(byte1, 10).toString(16);
while(value1.length<2){value1='0'+value1;}
var value2 = parseInt(byte2, 10).toString(16);
while(value2.length<2){value2='0'+value2;}
var value3 = parseInt(byte3, 10).toString(16);
while(value3.length<2){value3='0'+value3;}
var value4 = parseInt(byte4, 10).toString(16);
while(value4.length<2){value4='0'+value4;}
var value = value1 + value2 + value3 + value4;
var res = parseInt(value,16);
for (k = 0; k < arrSerial.length; k++) {
if (arrSerial[k] == realSerialN) {
if (k % 4 == 0) waterWMBusValue1 = res/1000;
if (k % 4 == 1) waterWMBusValue2 = res/1000;
if (k % 4 == 2) waterWMBusValue3 = res/1000;
if (k % 4 == 3) waterWMBusValue4 = res/1000;
return null;
}
}
return null;
}
function GetFlagError(byte1, num) {
var value = parseInt(byte1, 10).toString(2);
while(value.length<8){value='0'+value;}
if(num==1) return Number(value[7]);
if(num==2) return Number(value[6]);
if(num==3) return Number(value[5]);
if(num==4) return Number(value[4]);
if(num==5) return Number(value[3]);
if(num==6) return Number(value[2]);
if(num==7) return Number(value[1]);
if(num==8) return Number(value[0]);
return null;
}
return result;

You can test the converter before connecting the device. Open the Uplink wM-Bus Reader converter, enter edit mode and click the Test decoder function tab. Paste the sample input below into the Payload content field and press Test.

Sample input payload (Base64-encoded)
{
"applicationID": "3",
"applicationName": "Smartico_wmbus_readers",
"deviceName": "0000020",
"devEUI": "02aaaa0100000014",
"rxInfo": [{
"gatewayID": "647fdafffe00d228",
"uplinkID": "14b77859-1e6c-4668-8eb3-73900e49a33c",
"name": "tectelic_micro_lite_TECH",
"rssi": -89,
"loRaSNR": 7.5,
"location": {
"latitude": 48.44229794818326,
"longitude": 35.014479160308845,
"altitude": 144
}
}],
"txInfo": {
"frequency": 868500000,
"dr": 0
},
"adr": true,
"fCnt": 28,
"fPort": 33,
"data": "IAP1YwIAAAAATFo="
}
Expected decoded output
{
"deviceName": "0000020",
"deviceType": "wM-Bus Reader",
"attributes": {
"integrationName": "wM-Bus Reader Integration"
},
"telemetry": {
"REAL_TIME": "26.08.2020 16:38:14",
"SERIAL1": "66413314",
"SERIAL2": null,
"SERIAL3": null,
"SERIAL4": null,
"WATER_WMBUS_VALUE1": 19.546,
"WATER_WMBUS_VALUE2": null,
"WATER_WMBUS_VALUE3": null,
"WATER_WMBUS_VALUE4": null,
"FLG_LOW_BAT": 0,
"FLG_MOTION_DETECT": 0,
"FLG_MAGNET_DETECT": 0,
"FLG_TAMPER_DETECT": 0,
"FLG_POWER_ON": 0,
"FLG_POWER_BAT": 1,
"FLG_ERR_TIME": 0,
"FLG_CFG_DONE": 0
}
}

Create the integration

For more information about MQTT integrations in ThingsBoard, see the MQTT integration documentation.

  1. Go to Integrations center ⇾ Integrations and click + Add integration.
  2. Basic settings:
    • Set Integration type to MQTT.
    • Enable integration and Allow create devices or assets are on by default.
    • Click Next.
  3. Uplink data converter:
    • Select existing — choose the previously created Uplink wM-Bus Reader from the list.
    • Click Next.
  4. Downlink data converter:
    • Click Skip — only needed for RPC; can be added later.
  5. Connection:
    • Set your MQTT broker Host and Port.
    • Select the Credentials type (e.g. Anonymous).
    • Add at least one topic filter with QoS (e.g. application/3/device/+/rx, QoS 0 — At most once).
  6. Click Add to complete the integration setup.

Verify data

After the WM-LR transmits its first packet, a new device named after its serial number (like 0000020) appears automatically in Entities > Devices. You can also verify input and output data in Data converters > Uplink wM-Bus Reader > Events.

Create an asset

To display data on the dashboard, create an asset and add the device as a relation.

  1. Go to Entities ⇾ Assets and create a new asset named wM-Bus Reader with asset type wmbus-reader.

  2. Open the asset, go to the Relations tab, and add a relation to the device.

Import the rule chain

In addition to meter readings, the device reports status flags: low battery, tamper detection, and magnetic field exposure. These are displayed in an Alarm widget. Import the rule chain first to enable alarm processing.

  1. Download alarms_wmbus_reader.json and import it in Rule chains.

  2. Open the Root Rule Chain, add a link to the imported Alarms wMBus Reader rule chain, and save.

Import the dashboard

  1. Download dashboard_wmbus_reader.json and import it in Dashboards. See the dashboard import instructions.

  2. After importing, edit the dashboard alias and set it to the wM-Bus Reader asset created in the previous step.

The dashboard now displays live water meter readings from up to four wM-Bus meters and device health data from the Smartico WM-LR.