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
Explore the pros and cons of various reverse geocoding services supported by flespi.
Using plugins to resolve the coordinates of GSM base stations and Wi-Fi networks into position coordinates using Unwired Labs API.