How to split BLE data into plain parameters with a PVM plugin?

Getting plain parameters’ values from array-structured ‘ble.beacons’ parameters

In flespi, we receive BLE data in ‘ble.beacons’ parameters presented as a JSON array, with each beacon's data inside. However, to effectively use this data in flespi analytics and some platforms like Wialon, each BLE sensor should be presented as a separate parameter in the message with a fixed name determined by BLE ID, no matter what index in the beacons array it occupies. 

So, we prepared a pvm-code plugin template that can be used to store each attribute of BLE objects inside an array into a standalone message parameter. To simplify data usage, this script also converts long BLE beacon IDs into shorter hashes when formatting the flat parameter name.

Original message:

{
"ble.beacons": [
{
"id": "00026DA6-4FA2-4E98-8024-BC5B71E0893E:0000:0000",
"rssi": -60,
"temperature.sensor": 55,
"humidity.sensor": 40
},
{
"id": "100026DA6-4FA2-4E98-8024-BC5B71E0893E:0000:0000",
"rssi": -62,
"temperature.sensor": 59,
"humidity.sensor": 45
}
]
}

Here’s the result of the flespi device message with the parameters carefully parsed and injected:

  {
"ble.beacons.humidity.sensor.587557D7": 40,
"ble.beacons.humidity.sensor.EDB4C4C8": 45,
"ble.beacons.id.587557D7": "00026DA6-4FA2-4E98-8024-BC5B71E0893E:0000:0000",
"ble.beacons.id.EDB4C4C8": "100026DA6-4FA2-4E98-8024-BC5B71E0893E:0000:0000",
"ble.beacons.len": 2,
"ble.beacons.rssi.587557D7": -60,
"ble.beacons.rssi.EDB4C4C8": -62,
"ble.beacons.temperature.sensor.587557D7": 55,
"ble.beacons.temperature.sensor.EDB4C4C8": 59,
"timestamp": 1711612930.834509
}

The main block of PVM code, applicable to most situations, operates as follows: the code searches for a property named ‘ble.beacons’, then enters each object within a loop and iterates through all the properties it contains, registering a parameter of the form: #ble.beacons.’parameter_name’.’hash’. After that, it removes the 'ble. beacons' property, which contains an array with BLE data.

Please note: the hash calculation for the tag ID is used to identify the tag parameters because the clean ID

id: "100026DA6-4FA2-4E98-8024-BC5B71E0893E:0000:0000",

which the label sends, is too long and not suitable for adding to the parameter name. Therefore, a hash is used to create a small unique number for a group of parameters.

// Check if '.ble.beacons' property exists
optional .ble.beacons ==> array:
    // Count number of objects in the array
array_length ==> #ble.beacons.len
    // Iterate each object in the array
repeat[array_length, counter=$i, from=0]:
        // Process each object in the array
[$i] ==> object:
// Take the tag ID and make a hash from it that will be used as part of the parameter name.
.id ==> hash[32] ==> $hash32
            // Iterate all keys in the current object
foreach[$key]:
                // Log key value to the parameter with formated name
{$key} ==> #param["ble.beacons.%s.%X", $key, $hash32]
// Remove initial ble.beacons array from the final message
unset .ble.beacons

If the configuration tool of the tag allows you to add a name, you can use it.

            // Take the tag name that will be used as part of the parameter name.
.name ==> $name
            // Iterate all keys in the current object
foreach[$key]:
                // Log key value to the parameter with formated name
{$key} ==> #param["ble.beacons.%s.%s", $key, $name]

To filter the data that will be written to parameters, you can use the following condition:

                if $key == "temperature.sensor": // comparing the key (parameter name) and the desired text
                 {$key} ==> #param["ble.beacons.%s.%X", $key, $hash32] // Log only that parameter

Or you can use several conditions at once, altering the format name of a specific parameter.

            if $key == "temperature.sensor" || $key == "humidity.sensor":   // Сomparing the key (parameter name) and the desired text
{$key} ==> #param["ble.beacons.%s.%X", $key, $hash32] // Log the parameter
elif $key == "rssi": // One more comparison
{$key} ==> #param["ble.beacons.signal.strength.%X", $hash32] // ...

Done. By the way, here is the article on how to add BLE tag coordinates into device messages along with some real-life use cases for indoor monitoring.

To get recent updates for ble.beacons protocol we recommend subscribing to a dedicated changelog topic on our forum.


See also
Using plugins to resolve the coordinates of GSM base stations and Wi-Fi networks into position coordinates using Unwired Labs API.