# Tesenso M-Bus LoRaWAN

## Quickstart

{% tabs %}
{% tab title="QuickStart Guide EN" %}
{% file src="<https://3644989493-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MgVxJqlLMh-0vshmfk7%2Fuploads%2FPNMPj20lgW1I38baT25R%2FTesenso%20M-Bus%20QuickStart%20Guide%20V4-EN.pdf?alt=media&token=761e32e4-d9a8-4925-b5cb-ebd0373a01a3>" %}
{% endtab %}

{% tab title="QuickStart Guide DE" %}
{% file src="<https://3644989493-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MgVxJqlLMh-0vshmfk7%2Fuploads%2FTIAXVPbzQucDF4hThsdY%2FTesenso%20M-Bus%20QuickStart%20Guide%20V4-DE.pdf?alt=media&token=7c867d8f-fa17-4909-9600-6e6e74a909cb>" %}
{% endtab %}
{% endtabs %}

## Product Datasheet

{% tabs %}
{% tab title="Datenblatt DE" %}
{% file src="<https://3644989493-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MgVxJqlLMh-0vshmfk7%2Fuploads%2F6gElCJrdnWV2HvE2Cxon%2FTesenso%20M-Bus%20Datenblatt%201.3.pdf?alt=media&token=38ea45db-9a3d-4e5b-b6fe-4292ebde5a83>" %}
{% endtab %}

{% tab title="Datasheet EN" %}
{% file src="<https://3644989493-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MgVxJqlLMh-0vshmfk7%2Fuploads%2FuCKWgkgLLUuX5QpapAfV%2FTesenso%20M-Bus%20Datasheet%201.3.pdf?alt=media&token=6fb80e06-d4c8-40ed-b66e-305f7aefbf7f>" %}
{% endtab %}
{% endtabs %}

## Uplink documentation

{% tabs %}
{% tab title="V2.0 (currrent version)" %}

### M-BUS message formats

| Name:  | Length | MsgType | Data depending on MsgType |
| ------ | ------ | ------- | ------------------------- |
| Unit:  |        | Enum    |                           |
| Bytes  |        |         |                           |
| Range: | 0..255 | 0..127  |                           |

### Uplink message ports

<table data-header-hidden><thead><tr><th width="371"></th><th align="right"></th></tr></thead><tbody><tr><td><strong>Uplink message port:</strong> </td><td align="right">2</td></tr><tr><td><strong>Uplink message port for split messages</strong></td><td align="right">12</td></tr><tr><td><strong>Status Uplink message port:</strong></td><td align="right">50</td></tr></tbody></table>

### ENUM definitions

| MsgType Enum                   |    |                   |
| ------------------------------ | -- | ----------------- |
| 0                              | 0  | Status message    |
| 1                              | 1  | Scan Result       |
| 2                              | 2  | Telegram Response |
| 3                              | 3  | Read Meter        |
| 4                              | 4  | Read Meter Raw    |
| ...                            |    |                   |
| 123                            | 7B | HW\_ID\_UL        |
| 124                            | 7C | MCU\_ID\_UL       |
| 125                            | 7D | Firmware\_hash    |
| Port for ID-s (123-125) is 200 |    |                   |

### Message Types

### 0: Status message

{% hint style="info" %}
**Port 50**
{% endhint %}

| Name:                      | Length | MsgType | Voltage    | Temp | Saved slaves | Read interval | Flags | Status interval |     |
| -------------------------- | ------ | ------- | ---------- | ---- | ------------ | ------------- | ----- | --------------- | --- |
| Unit:                      |        | Enum    | 1/100 -170 |      | Count        | Min(s)        |       | Min(s)          |     |
| Bytes                      | 1      | 1       | 1          | 1    | 1            | 1             | 1     | MSB             | LSB |
| Range:                     | 8      | 0       |            |      |              |               |       |                 |     |
| Example                    | 08     | 0       |            |      |              |               |       |                 |     |
| 08 00 9e 30 00 03 a0 05 a0 |        |         |            |      |              |               |       |                 |     |

###

### 1: Scan Result

| Name:  | Length | MsgType | slave addresses |   |
| ------ | ------ | ------- | --------------- | - |
| Unit:  |        | Enum    |                 |   |
| Bytes  | 1      | 1       | X               |   |
| Range: |        | 1       |                 |   |

###

### 2: Telegram Response

| Name:  | Length | MsgType | Slave response |   |
| ------ | ------ | ------- | -------------- | - |
| Unit:  |        | Enum    |                |   |
| Bytes  | 1      | 1       | X              |   |
| Range: |        | 2       |                |   |

###

### 3: Read Meter

| 3: Read Meter |        | Meter properties block | Meter properties block |             |        |     |             |     |   |          |   |         |   |    |
| ------------- | ------ | ---------------------- | ---------------------- | ----------- | ------ | --- | ----------- | --- | - | -------- | - | ------- | - | -- |
| Name:         | Length | MsgType                | no. of slaves          | ID          | Medium | VIF | Volume      | ... |   |          |   |         |   |    |
| Unit:         |        | Enum                   | count                  | BCD encoded |        |     | BCD encoded |     |   |          |   |         |   |    |
| Bytes         | 1      | 1                      | 1                      | 1           | 1      | 1   | 1           | 1   | 1 | 1        | 1 | 1       | 1 | 10 |
| Range:        |        | 3                      |                        | HighByte    |        |     | LowByte     |     |   | HighByte |   | LowByte |   |    |

###

### 4: Read Meter Raw

{% hint style="info" %}
**Port 2**
{% endhint %}

|        |        |         |           |                        | Has to be decoded in the backend (contains all information) |
| ------ | ------ | ------- | --------- | ---------------------- | ----------------------------------------------------------- |
| Name:  | Length | MsgType | Slave No. | Full response telegram |                                                             |
| Unit:  |        | Enum    | Byte      |                        |                                                             |
| Bytes  | 1      | 1       | 1         | X                      |                                                             |
| Range: |        | 4       |           |                        |                                                             |

###

### 4: Read Meter Raw SPLIT

{% hint style="info" %}
**Port 12**
{% endhint %}

|        |        |         |           |         |                        | Has to be decoded in the backend (contains all information) |
| ------ | ------ | ------- | --------- | ------- | ---------------------- | ----------------------------------------------------------- |
| Name:  | Length | MsgType | Slave No. | Pointer | Full response telegram |                                                             |
| Unit:  |        | Enum    | Byte      | Byte    |                        |                                                             |
| Bytes  | 1      | 1       | 1         | 1       | X                      |                                                             |
| Range: |        | 4       |           |         |                        |                                                             |

###

### 123: HW\_ID\_UL

|        |         |         |
| ------ | ------- | ------- |
| Name:  | MsgType | HWID    |
| Unit:  | Enum    | version |
| Bytes  | 123     |         |
| Range: |         | 0..7    |

###

### 124: MCU\_ID\_UL

| Name:  | MsgType | MCU\_ID  |   |   |         |
| ------ | ------- | -------- | - | - | ------- |
| Unit:  | Enum    |          |   |   |         |
| Bytes  | 124     | HighByte |   |   | LowByte |
| Range: |         |          |   |   |         |

###

### 125: Firmware\_hash\_UL

<table><thead><tr><th width="171">Name:</th><th>MsgType</th><th>Firmware version and hash</th><th></th><th></th></tr></thead><tbody><tr><td>Unit:</td><td>Enum</td><td>String</td><td></td><td></td></tr><tr><td>Bytes</td><td>125</td><td>Size varies</td><td></td><td></td></tr><tr><td>Range:</td><td></td><td></td><td></td><td></td></tr></tbody></table>
{% endtab %}

{% tab title="V2.1" %}
(not available yet, coming soon)
{% endtab %}
{% endtabs %}

### Uplink Decoder

```
// V3.0 10.05.2022, copyright by Tesenso GmbH

//Code entry
if (msg.data) {
    var decoded = decodeFromHex(msg.data);
    decoded.ts = msg.ts;
    decoded.rssi = msg.rssi;
    decoded.snr = msg.snr;
    decoded.toa = msg.toa;
    decoded.frequency = msg.frequency;
    decoded.dr = msg.dr;
    decoded.bat = decodeBattery(msg.bat);
    decoded.hex = msg.data;

    return {
        msg: decoded,
        metadata: metadata,
        msgType: msgType
    };
} else {
    return {
        msg: msg,
        metadata: metadata,
        msgType: msgType
    };
}


function decodeFromHex(data) {
    // Decode uplink message
    var decoded = {};

    //Parse string as bytes
    var bytes = parseHexString(data);
    //scale to manage the different scales with none, one or more decimals on the meter.
    var scale = metadata.ss_scale;

    //various info that can be extracted
    var length = bytes[0];
    var msgType = bytes[1];
    var slaveCount = bytes[2];
    var startCharacter1 = bytes[3];
    var length1 = bytes[4];
    var length2 = bytes[5];
    var startCharacter2 = bytes[6];
    var c = bytes[7];
    var a = bytes[8];
    //72 or 76 -> variable; 73 or 77 -> fixed
    var ciField = bytes[9];
    var medium = data.substr(34, 2);
    var checkSum = bytes[36];


    //Different medium IDs, register positions vary
    if (medium == "02") {
        var volume = data.substr(72, 2) + data.substr(70,
            2) + data.substr(68, 2) + data.substr(66, 2);
        decoded.electricityMeterEnergyHt = parseInt(volume,
            16) * scale;
        volume = data.substr(88, 2) + data.substr(86, 2) +
            data.substr(84, 2) + data.substr(82, 2);
        decoded.electricityMeterEnergyNt = parseInt(volume,
            16) * scale;
    }
    if (medium == "03") {
        var volume = data.substr(66, 2) + data.substr(64,
            2) + data.substr(62, 2) + data.substr(60, 2);
        decoded.gasMeterVolume = parseInt(volume) * scale;
    }
    if (medium == "16") {
        var volume = data.substr(54, 2) + data.substr(52,
            2) + data.substr(50, 2) + data.substr(48, 2);
        decoded.waterMeter = parseInt(volume, 16) * scale;
    }

    return decoded;
}

//Helper functions
function parseHexString(hex) {
    for (var bytes = [], c = 0; c < hex.length; c += 2)
        bytes.push(parseInt(hex.substr(c, 2), 16));
    return bytes;
}

function decodeBattery(byte) {
    if (byte == 0) {
        return 'External power source';
    } else if (byte > 0 && byte < 255) {
        return byte / 254 * 100;
    } else {
        return 'Unknown battery state';
    }
}

function parseFloat(str) {
    var float = 0,
        sign, order, mantissa, exp,
        int = 0,
        multi = 1;
    if (/^0x/.exec(str)) {
        int = parseInt(str, 16);
    } else {
        for (var i = str.length - 1; i >= 0; i -= 1) {
            if (str.charCodeAt(i) > 255) {
                console.log('Wrong string parameter');
                return false;
            }
            int += str.charCodeAt(i) * multi;
            multi *= 256;
        }
    }
    sign = (int >>> 31) ? -1 : 1;
    exp = (int >>> 23 & 0xff) - 127;
    mantissa = ((int & 0x7fffff) + 0x800000).toString(2);
    for (i = 0; i < mantissa.length; i += 1) {
        float += parseInt(mantissa[i]) ? Math.pow(2, exp) :
            0;
        exp--;
    }
    return float * sign;
}
```

{% hint style="info" %}
All Downlinks shall be sent on **Port 3**
{% endhint %}

### Downlink samples

### Add secundary adress manually to EEPROM

| Name:  | Length | MsgType | ID          |   |   |         |
| ------ | ------ | ------- | ----------- | - | - | ------- |
| Unit:  |        | Enum    | BCD encoded |   |   |         |
| Bytes  | 1      | 1       | 1           | 1 | 1 | 1       |
| Range: | 5      | 133     | HighByte    |   |   | LowByte |

* 05 --> Length
* 85 --> MsgType
* 17670401 --> secondaryAdress of the meter

```json
058517670401
```

### Downlink for Scan M-Bus slave on the M-Bus

| Name:  | Length | MsgType | Retry |
| ------ | ------ | ------- | ----- |
| Unit:  |        | Enum    |       |
| Bytes  | 1      | 1       | 1     |
| Range: | 2      | 130     | 0..3  |

* 02 --> Length&#x20;
* 82 --> MsgType&#x20;
* 01 --> Retry

```
028201
```

### Delete saved slaves from EEPROM

| Name:  | Length | MsgType |
| ------ | ------ | ------- |
| Unit:  |        | Enum    |
| Bytes  | 1      | 1       |
| Range: | 1      | 131     |

* 01 --> Length&#x20;
* 83 --> MsgType&#x20;

```
0183
```

### **Change send Intervall:**

| Message Types |        |         |       |                     |                |   |
| ------------- | ------ | ------- | ----- | ------------------- | -------------- | - |
| Name:         | Length | MsgType | Flags | status msg interval | Meter interval |   |
| Unit:         |        | Enum    |       | Min(s)              | Min(s)         |   |
| Bytes         | 1      | 1       | 1     | MSB                 | LSB            | 1 |
| Range:        | 0..255 | 128     |       |                     |                |   |

**sample downlinks to change the intervall:**

* 05800000001E --> 30 minutes
* 05800000000F --> 15minutes
* 058000000005 --> 5minutes

### Troubleshoot Checklist:

* take a photo of the meter and the full installation
* power device
* make sure that the connection (wires/cables) are connected correctly


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tesenso.com/tesenso-products/hardware/tesenso-m-bus-lorawan.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
