While Sensirion BLE gadgets are cost effective and power efficient and feature high quality sensors, they are limited to BLE in terms of connectivity.
Their BLE advertisement signals can be grabbed with the MyAmbience app but it does not allow you to easily forward the data for further analysis.
In this article, we present a simple script allowing you to forward the measurements to a BLE broker. The code can be flashed to any ESP32 board having both BLE and WiFi capabilities.
PrerequisitesBefore going further you should note that the project has been created around PlatformIO, hence you should have it up and running.
Unfortunately, PlatformIO does not support the most recent arduino-esp32 therefore code from this demo is not compatible with ArduinoIDE (at the time of writing).ComponentsFor this demo we will take advantage of 2 libraries created by Sensirion and part of the Unified Prototyping Toolkit (UPT).
The first one is the Sensirion UPT BLE Auto Detection library which allows you to retrieve all BLE signals emitted by Sensirion gadgets or DiY gadgets (created using Sensirion Gadget BLE Arduino Lib). The library will automatically decrypt the BLE advertisement packages and extract the measurement data.
The second library is Sensirion UPT MQTT Client. It simply allows you to conveniently forward measurements to your MQTT broker.
The code for this example is very straightforward and is simply combining the examples of the 2 libraries.
On the top of the file we import the required libraries and the configuration file.Global objects are also created, the MQTT service, the BLE scanner, and a map that will be filled with the latest BLE data.
#include "Sensirion_upt_ble_auto_detection.h"
#include "MqttMailingService.h"
#include <Arduino.h>
#include <MeasurementFormatting.hpp>
#include "config.h"
using namespace sensirion::upt::core;
using namespace sensirion::upt::ble_auto_detection;
using namespace sensirion::upt::mqtt;
MqttMailingService mqttMailingService;
SensirionBleScanner bleScanner = SensirionBleScanner();
std::map<uint16_t, std::vector<Measurement>> lastBleScanSamples;In the setup function, most of the code concerns the configuration of the MQTT service. We set the broker URI, the topic, and the function used to derive the topic suffix from the measurement.
The library defines the topic for a message using the following logic:
- First, one can configure a prefix common to all messages sent by the device (i.e. with the device identifier).
- Second, for each measurement a suffix can be generated according to the measurement metadata (i.e. one topic per data type, per sensor,...). In this case we use
MeasurementToTopicSuffixEmptywhich means that we will not add anything to the topic prefix.
In this case, to simplify this minimal example, we use MeasurementToTopicSuffixEmpty. This means all the messages will be sent to the topic set in the setGlobalTopicPrefix (no suffix will be appended).
Finally using startWithDelegatedWiFi we ask the library to take care of the WiFi connection for us. By doing so, it will create a watchdog ensuring that the connection won't go down.
We can then start the bleScanner and the setup routine is complete.
void setup() {
Serial.begin(115200);
delay(2000); // Wait for potential serial connection
// Configure the MQTT mailing service
mqttMailingService.setBrokerURI(MQTT_BROKER_URI);
mqttMailingService.setGlobalTopicPrefix(MQTT_TOPIC_PREFIX);
// mqttMailingService.setSslCertificate(MQTT_SSL_CERT);
mqttMailingService.setMeasurementMessageFormatterFn(FullMeasurementFormatter{});
mqttMailingService.setMeasurementToTopicSuffixFn(MeasurementToTopicSuffixEmpty{})
bool blockingStart = true;
mqttMailingService.startWithDelegatedWiFi(WIFI_SSID, WIFI_PASSWORD, blockingStart);
mqttMailingService.sendTextMessage("Device connected !", "status");
bleScanner.begin();
}In the loop function, we simply retrieve the latest BLE advertisements and then iterate through all the BLE devices and all their measurements in order to forward each of them to the MQTT broker.Once everything has been sent, the buffer holding the measurements is cleared.
The last call is ensuring that the BLE scanner never stops, it gets restarted in case of an error.
void loop() {
delay(1000);
bleScanner.getSamplesFromScanResults(lastBleScanSamples);
// Iterate through all devices and their measurements
for (const auto& device : lastBleScanSamples) {
for (const auto& measurement : device.second) {
// Send each measurement to MQTT
bool successful = mqttMailingService.sendMeasurement(measurement);
if(!successful){
ESP_LOGE("MAIN", "Failed to send measurement");
}
}
ESP_LOGD("MAIN", "Sent measurements for device ID: %u", device.first);
}
lastBleScanSamples.clear();
delay(100);
// ensure scanning is restarted in case of errors.
bleScanner.keepAlive();
}ConclusionIn this quick demo we discovered how to forward measurements from Sensirion BLE gadgets to an MQTT broker using a simple ESP32.











Comments