miro
Click
Payload Format
1. Overview
The payload of up and downlink messages consists of an arbitrary number of data structs (DS) of different types and lengths.
DS 1 | DS 2 | … | DS n |
---|
Each data struct is a combination of a header and the actual data payload:
L | T | payload |
---|
The header consits of two fields:
Field | Description |
---|---|
L |
Length of data struct, 1 byte, not including the length byte itself |
T |
Data struct type, 1 byte |
2. Uplinks
There are three distinct uplink payloads:
-
Regular Status Message
All uplinks are sento to LoRaWAN port 15.
2.1. Button Press
On every button press a message is sent to the network. The button press message is either sent confirmed or unconfirmed depending on current settings. The message consists of two data sections: Button state and Used charge
The message reports to different button state bit fields. The first field represents the activating button(s), which is the button that has been registered first. Only one bit will be set if ambigious button press is off. If it is set to on one ore more bits might be set, indicationg, that more than one button has been pressed at the same time. Only activated buttons will be reported.
After the button debounce time has passed, a second reading of all active buttons will is taken and reported int the bit field second reading.
For all bit fields, buttons are encoded as in
Bit (within bit field) | Button |
---|---|
0 |
North (N), top |
1 |
East (E), right |
2 |
South (S), bottom |
3 |
West (W), left |
Byte | Size | Description | Format |
---|---|---|---|
0 |
1 |
Message length (0x04) |
uint8 |
1 |
1 |
Message type (0x01) |
uint8 |
2 |
1 |
Bit mask representing active buttons: |
Bitfield |
3-4 |
2 |
Counter since last reset (little endian) |
uint16 |
Rough approximation of used charge in uAh since last reset. Bytes are encoded in little endian format.
Byte | Size | Description | Format |
---|---|---|---|
0 |
1 |
Message length (0x05) |
uint8 |
1 |
1 |
Message type (0x02) |
uint8 |
2-5 |
4 |
Used charge in uAh (little endian) |
uint32 |
04:01:51:A5:00:05:02:20:12:00:00
First Button |
N (0b0001) |
All Buttons |
NS (0b0101) |
Button Count |
165 |
Used Charge |
4640 uAh |
2.2. Status Message
The device sends a regular status messages at a configurable interval. The status message is always unconfirmed, regardless of the settings.
The Status message can be used to detect low batteries. An miro Click will stop working at 1.8V. 2.0V is therefore a good value to use for critical battery alerts. It may be useful to already create an alert at around 2.4V, in order to know when the device slowly reaches low battery levels.
The status message consists of the following data structs. Please note, depending on the LoRaWAN region not all data structs may be present.
Used Charge
See data section used charge above.
Battery Voltage and Temperature
Report current battery voltage and MCU temperature.
Byte | Size | Description | Format |
---|---|---|---|
0 |
1 |
Message lenght (0x03) |
uint8 |
1 |
1 |
Message type (0x03) |
uint8 |
2 |
1 |
Current battery Voltage in 10 mV with an offset of 170. To calculate volts: (x + 170)/100 |
uint8 |
3 |
1 |
Current MCU temperature in °C |
uint8 |
Current Configuration
Report current configuration.
Byte | Size | Description | Format |
---|---|---|---|
0 |
1 |
Message length (0x05) |
uint8 |
1 |
1 |
Message type (0x04) |
uint8 |
2 |
1 |
Bit mask representing active buttons: |
Bitfield |
3 |
1 |
Flags, bitwise or combination: |
Bitfield |
4-5 |
2 |
Status interval in minutes |
uint16 |
05:02:10:00:00:00:03:03:AA:28:05:04:0F:F8:A0:05
Used Charge |
16 uAh |
Battery Voltage |
3.4 V |
Internal Temperature |
40° C |
Button Configuration |
0x0F → All buttons enabled |
Configuration Flags |
0b11111100 → Everything enabled |
Status Message Intervall |
1440 minutes (1 day) |
2.3. Firmware Hash
The firmware hash message is sent once after successfully joining the network. The hash value can be used to identify the current firmware version of the device
Byte | Size | Description | Format |
---|---|---|---|
0 |
1 |
Message length (0x05) |
uint8 |
1 |
1 |
Message type (0x05) |
uint8 |
2-5 |
4 |
Firmware hash |
uint32 |
05:05:23:52:D6:59
Git Hash |
59d65223 |
3. Downlinks
Downlink messages are used to change the configuration of the device. They use the same general payload format as uplinks.
All downlinks must be sent on the LoRaWAN port 3! |
3.1. Device Configuration
The device configuration message type is used to set general device configuration.
Message type T = 0x80 and length L = 0x06.
Byte | Size | Description | Format |
---|---|---|---|
0 |
1 |
Message lenght (0x06) |
uint8 |
1 |
1 |
Message type (0x81) |
uint8 |
2 |
1 |
Button configuration mask: |
Bitfield |
3 |
1 |
Flags, combination of: |
Bitfield |
4-5 |
2 |
Status interval in minutes |
uint16 |
6 |
1 |
Button debounce time in milliseconds |
uint8 |
06:81:0F:F8:A0:05:1E
Flags |
Duty Cycle: On |
Status interval |
1440 minutes (1 day, 0x05A0) |
Button Debounce Time |
30 ms |
4. Decoder example
function decodeMiroClick(fPort, bytes) {
// Decode an uplink message from a buffer
// (array) of bytes to an object of fields.
var decoded = {};
function map(button) {
r = "";
if (button & 1) r += "N";
if (button & 2) r += "E";
if (button & 4) r += "S";
if (button & 8) r += "W";
return r;
}
if (fPort == 15) {
n = bytes.length;
idx = 0;
while (n > idx) {
s = bytes[idx++];
decoded.type = bytes[idx];
if (bytes[idx] == 1) {
decoded.buttons_first = map(bytes[idx + 1] & 0xF);
decoded.buttons = map((bytes[idx + 1] >> 4) & 0xF);
decoded.count = bytes[idx + 2] + (bytes[idx + 3] << 8);
} else if (bytes[idx] == 2) {
decoded.uah = bytes[idx + 1] + (bytes[idx + 2] << 8) + (bytes[idx + 3] << 16) + (bytes[idx + 4] << 24);
} else if (bytes[idx] == 3) {
decoded.iTemp = bytes[idx + 2];
decoded.vBatt = (bytes[idx + 1] + 170) / 100.0;
} else if (bytes[idx] == 4) {
decoded.buttonCfg = map(bytes[idx + 1] & 0xF);
decoded.flags = bytes[idx + 2].toString(16);
decoded.statusCycle = bytes[idx + 3] + (bytes[idx + 4] << 8);
} else if (bytes[idx] == 5) {
decoded.firmwareHash = (bytes[idx + 1] + (bytes[idx + 2] << 8) + (bytes[idx + 3] << 16) + (bytes[idx +4] << 24)).toString(16);
}
idx += s;
}
}
return decoded;
}