Bluetooth Low Energy (BLE) has become an important part of modern connected devices. From wireless sensors and fitness trackers to industrial monitoring systems and smart home applications, BLE makes it possible for devices to communicate efficiently while keeping power consumption low.
For developers who are just getting started, however, understanding Bluetooth Low Energy can sometimes feel complicated. Terms like advertising, scanning, central and peripheral roles, GATT, services, and characteristics can be confusing at first. Even developers with programming experience may find it challenging to understand how these concepts work together in a real application.
To make learning BLE easier and more practical, we’re excited to introduce BleuIO Academy, a new learning resource designed to help anyone understand Bluetooth Low Energy and gradually move toward building real BLE applications.
BleuIO Academy is designed around a simple idea: learning Bluetooth Low Energy should be approachable, structured, and practical.
Rather than jumping directly into complicated code or technical specifications, the Academy starts with the fundamentals. Readers can first understand what BLE is, how it differs from traditional Bluetooth, and why it is widely used in connected devices.
From there, lessons gradually introduce the different parts of BLE communication, including advertising, device discovery, connections, GATT, and data exchange.
Each lesson focuses on a specific topic and uses clear explanations, illustrations, diagrams, and practical examples to make technical concepts easier to understand.
The Academy follows a structured learning path, but readers don’t have to start from the beginning. Developers looking for information about a particular BLE topic can explore individual lessons directly.
Who Is BleuIO Academy For?
We created BleuIO Academy for people with different levels of experience.
If you’re completely new to Bluetooth Low Energy, the beginner lessons provide a starting point without requiring previous BLE knowledge. You can learn the terminology, understand how devices communicate, and become familiar with the concepts that appear throughout BLE development.
If you’re already a software developer, the Academy can help you connect your programming knowledge with Bluetooth communication. Understanding how BLE devices advertise, establish connections, and exchange data is an important foundation before developing applications with languages such as Python, JavaScript, or C#.
For embedded developers, IoT engineers, and more experienced BLE users, the learning path also includes topics such as communication architecture, device security, performance, power consumption, troubleshooting, and real-world system design.
Whether you’re a student exploring wireless technology, a hobbyist working on an electronics project, or an engineer developing a connected product, the goal is to provide useful information that you can apply to your own work.
Go Beyond Theory with Hands-On BLE Learning
Reading about Bluetooth Low Energy is useful, but observing real BLE communication makes the concepts much easier to understand.
That’s why practical learning is an important part of BleuIO Academy.
Where appropriate, lessons include Try It Yourself sections that guide readers through real BLE operations using a BleuIO USB dongle and the BleuIO Web App.
For example, when learning about BLE advertising and discovery, you can use the Web App to scan for nearby Bluetooth Low Energy devices, observe scan results, and become familiar with the information available from advertising devices.
The exercises explain what you need, which steps to follow, what to look for in the results, and how the activity relates to the topic being taught.
The BleuIO Web App provides a convenient browser-based environment for supported BLE operations, allowing developers to experiment with their dongle without first building a separate application. It requires a compatible desktop browser and computer.
Not every lesson requires hardware. Many concepts can be understood through explanations, diagrams, and interactive learning activities. When a hands-on demonstration is useful, the Academy shows how to take that next step.
From Understanding BLE to Writing Real Code
Understanding BLE concepts is only the beginning. The next challenge is applying that knowledge in software and hardware projects.
As BleuIO Academy grows, we’re expanding the learning path to cover practical BLE programming and development using technologies such as Python, JavaScript, Node.js, React, and embedded development platforms.
The goal is to help learners move naturally from understanding a concept to implementing it.
For example, someone learning about BLE scanning can eventually build a program that discovers nearby devices. Someone studying GATT services and characteristics can move on to reading sensor measurements, receiving notifications, or creating an application that displays live data.
We’ll also connect relevant lessons to existing projects available on the BleuIO real world projects, where developers can explore practical applications involving sensors, development boards, gateways, and different programming environments.
These examples provide an opportunity to see how BLE concepts are used outside a textbook and how they fit into complete applications.
A Structured Learning Path That Will Keep Growing
BleuIO Academy is organized into eight learning modules, covering the journey from introductory BLE concepts to more advanced development and troubleshooting.
The first module, Introduction to Bluetooth Low Energy, is available and covers the fundamentals, how BLE works, communication roles, comparisons with other wireless technologies, and common applications.
We’ve also started publishing lessons about BLE architecture, advertising, scanning, and device discovery.
Additional topics are already included in the learning roadmap and are marked as Coming Soon. These will be published gradually as new educational material, diagrams, code examples, and practical exercises are prepared.
We want the Academy to grow into a dependable reference that developers can return to whenever they’re learning something new or working through a Bluetooth Low Energy problem.
Start Learning with BleuIO Academy
BleuIO Academy is freely accessible through the BleuIO website. You don’t need an account to start reading the lessons, and you can explore the topics at your own pace.
If you’re new to BLE, we recommend beginning with the fundamentals and following the lessons in order. If you already have experience, you can navigate directly to the topics that interest you.
We’re looking forward to expanding this resource with more tutorials, practical code examples, interactive explanations, and real-world BLE projects.
Our hope is that BleuIO Academy becomes a useful place for the Bluetooth developer community to learn, experiment, and build with greater confidence.
Whether you’re discovering Bluetooth Low Energy for the first time or developing your next connected application, we hope you’ll find something useful in BleuIO Academy.
RSSI analysis becomes much easier when you can see the signal changing instead of watching a stream of numbers in a terminal. A chart makes it possible to notice movement, sudden drops, periods of instability, and differences between devices almost immediately.
In this project, we use a BleuIO USB dongle with Python and Plotly Dash to build a live BLE signal strength analyzer. The application scans nearby BLE advertisers, lets us select a device, and follows its RSSI over time. It also provides a quick overview of every device currently being discovered.
This is intended as a starting point rather than a complete positioning or ranging system. If you already work with RSSI, the dashboard gives you a practical base for collecting observations, testing an environment, and extending the analysis for your own use case.
What the analyzer provides
The dashboard is organized around one selected BLE device. Its current RSSI, smoothed RSSI, recent trend, and signal stability appear directly above a live time-series chart. The raw readings remain visible, so the processed line never hides what the dongle actually received.
Below the main analysis, the Discovered Now section compares the latest RSSI values from nearby devices. An RSSI distribution chart shows how the selected device’s readings are spread across the recent observation window.
This combination is useful when you want to answer practical questions such as whether a signal is consistently weak, whether it is changing direction, or whether an apparently stable device is producing occasional large variations.
The application uses pySerial to communicate with BleuIO and Plotly Dash for the local dashboard. BleuIO handles the BLE radio operation, so the Python application only needs to work with its serial AT-command interface.
Download and install the project
Clone the repository and move into the project directory:
git clone https://github.com/smart-sensor-devices-ab/bleuio-rssi-analyzer.git
cd bleuio-rssi-analyzer
On macOS or Linux, create a virtual environment and install the dependencies:
Connect the BleuIO dongle before starting the application. BleuIO briefly exposes its bootloader after power-up, so allow approximately 15 seconds for the normal application serial port to appear.
The serial-port menu only shows ports identified as BleuIO devices. On macOS, this normally looks like /dev/cu.usbmodem.... On Windows, the dongle may appear as a generic USB Serial Device (COMx), so the application also recognizes BleuIO by its USB vendor and product identifiers.
Select the dongle and click Start scan. The application places BleuIO in central role and repeatedly performs a short timed scan using AT+GAPSCAN=1. Repeating the timed scan gives the dashboard a continuing series of fresh RSSI observations instead of a single discovery result. The command behavior is documented in the BleuIO AT command reference.
As advertisements are received, nearby addresses appear in the BLE device menu. Select the device you want to examine, and the analysis area updates immediately.
Follow a selected signal
The Current RSSI card displays the most recent reading. This value is useful for immediate feedback, but normal radio variation can make it jump even when neither device has deliberately moved.
The Smoothed RSSI view makes the overall movement easier to follow. The project first applies a short median filter to reduce isolated spikes, followed by an exponentially weighted moving average that gives more importance to recent observations. The original samples remain visible as dots, while the smoothed result appears as the blue line.
This processing is deliberately lightweight. It is enough to make the live chart readable, but it is also easy to replace if your experiment needs a Kalman filter, a different smoothing window, or no filtering at all.
Read the trend and stability indicators
The Recent Trend card compares the latest smoothed value with the recent signal history. A change of at least 4 dB is described as Getting stronger or Getting weaker. Smaller changes are shown as Stable. The card also displays the measured change, making the label easy to interpret rather than presenting it as an unexplained classification.
The Signal Stability card looks at the variation among the latest raw readings. A tightly grouped signal is labeled Steady. Greater variation is reported as Variable or Unstable. Strength and stability are treated separately: a weak signal can still be steady, and a strong signal can fluctuate considerably.
These thresholds are sensible defaults for exploring a signal, not universal BLE rules. They are kept in a small analysis module so they can be adjusted for the advertising interval, environment, antenna, and behavior of the device being studied.
Compare nearby devices
The Discovered Now chart provides context for the focused analysis. It shows the latest RSSI from every address found during the scan, ordered from stronger to weaker signals. This is useful when choosing a target or checking how crowded the local BLE environment is.
The distribution beside it belongs only to the selected device. It counts how often recent readings occurred within each RSSI range. A narrow group of bars usually accompanies a steadier signal, while a wider spread reveals more variation. The chart can be especially useful when comparing two locations or antenna orientations that have a similar average RSSI but different consistency.
Try a simple observation
Choose a BLE advertiser that sends packets regularly and leave it in a fixed position. Let the analyzer collect readings for a short period, then change one condition at a time: rotate the device, move it farther away, place an obstacle between it and BleuIO, or walk through the signal path.
The raw samples show the immediate radio response. The smoothed line makes the larger movement easier to see, while the trend and stability cards provide a compact summary. The distribution shows whether the new condition changed only the average signal or also made it more variable.
The goal is not to turn RSSI into an exact ruler. Bluetooth radio measurements are affected by the environment, reflections, antenna orientation, and the human body. The Bluetooth SIG notes that newer Bluetooth Channel Sounding is more reliable for accurate ranging than approaches that use RSSI as a distance proxy. The Bluetooth Low Energy primer provides useful background on that distinction.
For this project, RSSI is used for what it does well: observing relative signal behavior, detecting meaningful changes, and building an experiment around real measurements.
Take the project further
The source is intentionally compact so it can be adapted. A next version could save readings to CSV, compare multiple selected devices, add experiment markers, calculate packet reception rates, or load a calibration profile for a known environment. The analysis functions can also be replaced without changing the BleuIO serial scanner or the dashboard structure.
With a live view of both raw and processed RSSI, the project turns BleuIO into a useful signal exploration tool—and a practical foundation for more focused BLE research.
We’re pleased to announce the release of BleuIO firmware v2.8.0.6, introducing new Bluetooth Low Energy (BLE) connection controls and improvements to DUAL mode reliability.
This update gives developers greater flexibility in managing MTU (Maximum Transmission Unit) negotiation while ensuring more consistent connection behavior when operating in DUAL mode.
The new AT+REQMTU command allows developers to manually initiate a GATT client (GATTC) MTU exchange at any point after establishing a BLE connection.
MTU determines the maximum size of an ATT packet exchanged between connected BLE devices. Negotiating an appropriate MTU can help improve data transfer efficiency.
New command:
AT+REQMTU
With this feature, developers can:
Request MTU negotiation whenever needed after connection.
Gain greater control over BLE communication workflows.
Simplify testing and debugging of MTU-related behavior.
This functionality is similar to manual MTU requests available in BLE development tools such as nRF Connect.
2. Automatic MTU Negotiation Control with AT+AUTOMTU
Firmware v2.8.0.6 also introduces AT+AUTOMTU, allowing developers to enable or disable automatic MTU negotiation during connection parameter updates.
New commands:
AT+AUTOMTU=1 — Enable automatic MTU negotiation.
AT+AUTOMTU=0 — Disable automatic MTU negotiation.
When automatic negotiation is disabled, developers can use AT+REQMTU to trigger MTU exchanges manually.
Together, these commands provide greater flexibility for applications requiring precise BLE connection management.
Improved DUAL Mode Connection Reliability
This release also resolves an intermittent issue where BleuIO could initialize into the incorrect client or server role while operating in DUAL mode.
With the latest firmware, BleuIO now correctly determines its role based on the connection type:
Incoming connection: BleuIO operates in the server role.
Outgoing connection: BleuIO switches to the client role.
This fix ensures more predictable connection behavior for applications that use both BLE central and peripheral functionality.
How to Update Your BleuIO
There are two convenient ways to update your BleuIO to firmware v2.8.0.6.
Option 1: Download and Install the Latest Firmware
You can download the BleuIO firmware and follow the firmware update instructions in our official documentation:
We’re pleased to announce the release of BleuIO Pro firmware v1.0.7.3, introducing new MTU negotiation commands, improved GATT discovery stability, and optimized handling of complex Bluetooth Low Energy (BLE) devices.
This update gives developers greater control over BLE connections while improving performance and reliability when working with peripherals containing large GATT databases.
New MTU Negotiation Controls
Firmware v1.0.7.3 introduces two new AT commands for managing MTU negotiation.
AT+REQMTU – Request MTU Exchange Manually
The new AT+REQMTU command allows developers to initiate a GATT client MTU exchange at any point after establishing a BLE connection.
This provides greater flexibility when testing peripheral behavior, debugging connections, or managing specific connection workflows.
AT+AUTOMTU – Control Automatic MTU Negotiation
The new AT+AUTOMTU command lets developers enable or disable automatic MTU negotiation during connection parameter updates.
AT+AUTOMTU=1 – Enable automatic MTU negotiation.
AT+AUTOMTU=0 – Disable automatic MTU negotiation.
When disabled, developers can use AT+REQMTU to trigger the exchange manually, allowing more predictable connection handling in automated scripts and applications.
Improved GATT Discovery Stability
This release addresses an issue where BleuIO Pro could unexpectedly reset while discovering services and characteristics on peripherals with exceptionally large GATT databases.
The discovery engine has been redesigned to use a sequential streaming architecture instead of memory-intensive hierarchical caching.
With this improvement, GATT attributes are processed dynamically and sent to the USB interface as they are discovered.
Key benefits include:
Reduced memory consumption during GATT discovery.
Improved connection stability with complex BLE peripherals.
Support for up to 165 characteristics within a single service.
More efficient processing of large GATT profiles.
These improvements apply to the following commands:
AT+GETSERVICES
AT+GETSERVICESONLY
AT+GETSERVICEDETAILS
GATT Discovery Output Changes
With the new streaming architecture, discovered GATT attributes are reported immediately as they are processed.
One small change affects the presentation order of descriptors. Previously, descriptors such as CCCDs (0x2902) appeared directly after their associated characteristics. They are now grouped at the end of the corresponding service block.
Important: All JSON fields in verbose mode and standard text-mode output strings remain unchanged. Only the order of descriptor entries has been modified.
Developers using custom parsers that depend on descriptor ordering should review their implementation to ensure compatibility.
How to Update Your Firmware
Updating your BleuIO Pro is straightforward.
You can download the latest firmware and follow the step-by-step update instructions in our official documentation:
Both methods provide a simple way to get your BleuIO Pro running the latest firmware.
We recommend updating to v1.0.7.3 to benefit from the latest MTU controls, improved GATT discovery stability, and support for larger peripheral profiles.
In this tutorial we will use CircuitPython to turn a Cytron MOTION 2350 Pro into a HibouAir scanner. The board’s RP2350 has no Bluetooth radio of its own. A BleuIO dongle in the board’s USB-A host port provides Bluetooth Low Energy, and a short CircuitPython program talks to it with ordinary AT commands.
The program scans for air quality monitoring device HibouAir advertisements, decodes them, and keeps the latest readings in global variables. One of them, the PM10 value from a HibouAir PM sensor, is ready to be used by the rest of your program. As an example, the program turns a hobby servo on one of the board’s servo ports into an analog PM10 gauge.
Everything runs on the board. No computer is needed once the code is in place, and the HibouAir sensors do not need to be paired.
With circup installed on your computer, one command copies both:
circup install asyncio
Everything else the program uses is built into CircuitPython: usb_host, usb.core, json, binascii, microcontroller, pwmio and time. The servo is driven with pwmio directly, so it needs no extra library. No boot.py is needed.
What Does This Project Do?
1. The board becomes a USB host
The MOTION 2350 Pro’s USB-A port is driven by the RP2350’s PIO. CircuitPython starts it with usb_host.Port on GPIO24 and GPIO25. The board definition has no named pins for this port, so the program uses the raw pins.
2. CircuitPython finds BleuIO
The program waits until a device with vendor ID 0x2DCF and product ID 0x6002 appears, which is BleuIO. It selects the dongle’s configuration and sets DTR and RTS, so that BleuIO starts sending its output.
3. The dongle is brought into a known state
BleuIO remembers what it was doing, so a scan from an earlier run may still be going. The program first sends Ctrl-C three times to stop it. It then throws away everything the dongle sends until it has been quiet for 0.3 seconds. After that it sends:
ATE0, which turns echo off
ATV1, which turns verbose mode on, so every reply is one line of JSON
4. BleuIO scans for HibouAir only
AT+FINDSCANDATA=FF5B07
This reports only advertisements that contain FF5B07. FF is the AD type for manufacturer-specific data, and 5B 07 is HibouAir’s company ID, 0x075B, as it appears in the packet. Each result arrives as a line such as:
The program walks the advertisement’s AD structures until it finds the HibouAir manufacturer data. This works whether or not the flags field comes first. Counting from the company ID, the sensor beacon (beacon type 0x05) holds:
Offset
Field
Format
2
Beacon type
0x05 for sensor readings
3
Board type
0x03 is the PM sensor
4–6
Sensor ID
as shown in the HibouAir app, e.g. 22026A
9
Pressure
16-bit little-endian, tenths of hPa
11
Temperature
16-bit little-endian, signed, tenths of °C
13
Humidity
16-bit little-endian, tenths of %rh
17
PM1.0
16-bit little-endian, tenths of µg/m³
19
PM2.5
16-bit little-endian, tenths of µg/m³
21
PM10
16-bit little-endian, tenths of µg/m³
23
CO2
16-bit big-endian, ppm
6. The readings are kept in global variables
pm10: the latest PM10 value in µg/m³, or None until a PM sensor has been heard
pm10_sensor: the ID of the sensor it came from
pm10_time: time.monotonic() when it arrived, so that a stale value can be recognised
sensors: a dictionary with everything the last beacon of every HibouAir sensor said, keyed by sensor ID
If you have more than one PM sensor, set PM_SENSOR_ID to the one pm10 should follow. If nothing has been heard for 15 seconds, the program starts the scan again.
Showing PM10 on a Servo Gauge
The MOTION 2350 Pro has eight servo ports, on GP0 to GP7, each with a PWM channel of its own. The program drives a servo on GP0 as a needle: 0 µg/m³ at 0 degrees, and 100 µg/m³ or more at 180 degrees.
With that full scale, the PM10 limits the HibouAir app uses fall at simple angles. That is where to draw the bands on a paper scale behind the servo arm:
PM10
Level
Needle
0–20 µg/m³
Good
0–36°
20–50 µg/m³
Fair
36–90°
50–100 µg/m³
Poor
90–180°
100 µg/m³ and above
Bad
180°
The gauge is its own asyncio task, beside the reader and the command logic:
It sends a 50 Hz servo signal, from 500 µs at 0 degrees to 2500 µs at 180.
It moves the needle 2 degrees every 20 ms, so the arm swings to a new reading instead of jumping.
At start it sweeps once across the whole scale. A servo that is not connected is then noticed at once, instead of being taken for clean air.
Once the needle has been still for half a second, the pulses stop. A servo told to hold a position holds it actively, and at 0 degrees, the commonest reading of all, it pushes against its end stop and hums. Without pulses an ordinary hobby servo goes quiet and stays where it is.
The pulses start again when a new reading moves the needle by at least one degree, so readings of 0.0 and 0.1 µg/m³ taking turns do not wake it.
Connect the servo to the GP0 servo header, matching the servo cable to the markings next to the header. Check Cytron’s datasheet for how the servo ports are supplied before connecting a larger servo.
The settings are at the top of code.py:
SERVO_PIN: the port, board.GP0 to board.GP7
PM10_FULL_SCALE: the PM10 value at 180 degrees
SERVO_MIN_US and SERVO_MAX_US: the pulse widths at the ends. Narrow them if your servo strains at its end stops.
SERVO_STEP_DEG: how fast the needle moves
SERVO_REST_S and SERVO_DEADBAND_DEG: how long the needle is still before it rests, and how far a reading must move it to wake it
The board’s four DC motor drivers, on GP8 to GP15 (board.M1A to board.M4B in CircuitPython), would suit a different use of the same value, such as running a fan faster as PM10 rises.
Why the Flush After Ctrl-C Matters
Ctrl-C stops the scan, but whatever BleuIO had already queued still arrives afterwards. Often the last piece is a line cut off in the middle, sometimes with a byte that is not valid UTF-8.
In early versions of this program, a reader that tried to decode that line before removing it from its buffer stuck on it. Every later piece of data was appended behind the same broken line, and the program heard nothing more, in about half of all restarts.
The program now does two things:
It removes each line from the buffer before decoding it, so a broken line costs that line only.
It discards everything until the dongle has been quiet before sending the next command.
With both in place, the start-up worked every time in repeated tests, whether the dongle was fresh (echo on, verbose off) or left in verbose mode by an earlier run.
How to Run the Project
Step 1: Install CircuitPython
Download the CircuitPython UF2 for the Cytron MOTION 2350 Pro and put the board into its UF2 bootloader mode. On RP2350 boards this is done by holding BOOT while pressing RESET, or while connecting the USB cable. Copy the UF2 to the RP2350 drive that appears. The board restarts as a drive named CIRCUITPY.
Step 2: Add the libraries
Run circup install asyncio, or copy the asyncio folder and adafruit_ticks.mpy from the library bundle into CIRCUITPY/lib.
Step 3: Copy the program
Save the code at the end of this post as code.py on the CIRCUITPY drive. CircuitPython starts it as soon as the file is saved.
Step 4: Connect BleuIO
Insert the BleuIO dongle into the board’s USB-A port. Do not connect BleuIO to the computer for this setup.
Step 5: Connect the servo (optional)
Plug the servo into the GP0 servo header. It sweeps once from 0 to 180 degrees and back when the program starts, then follows PM10, and goes quiet whenever the needle is still.
Step 6: Watch the serial console
Open the board’s serial console at 115200 baud. Use Mu, Thonny or the CircuitPython web workflow, or on macOS and Linux:
screen /dev/cu.usbmodem2101 115200
The device name differs from computer to computer. If the console shows raw REPL; CTRL-B to exit, an editor has left it in raw REPL mode: press Ctrl-B, then Ctrl-D to start code.py.
Expected Output
BleuIO dongle found! (0x2dcf:0x6002)
CDC Control Lines (DTR/RTS) enabled.
Starting background USB reader task...
Starting the HibouAir scan...
[Sending]: ATE0
[Sending]: ATV1
[Sending]: AT+FINDSCANDATA=FF5B07
[HibouAir 22026A] PM10 0.1 ug/m3 PM2.5 0.1 PM1 0.0 21.8 C
[HibouAir 22008C] board 0x04, 21.5 C, 39.8 %rh, CO2 459 ppm
[HibouAir 220095] board 0x04, 20.8 C, 42.9 %rh, CO2 411 ppm
[HibouAir 22005A] board 0x04, 19.6 C, 44.2 %rh, CO2 721 ppm
[HibouAir 220265] board 0x09, 19.8 C, 45.5 %rh, CO2 533 ppm
Every HibouAir sensor in range appears with its ID. Lines from the PM sensor show the particle readings; the others show temperature, humidity and CO2. Each new PM line also updates pm10.
This project is a practical example of how BleuIO can bring Bluetooth Low Energy connectivity to development boards without built-in Bluetooth support. Using the Cytron MOTION 2350 Pro and CircuitPython, we demonstrated how to scan for HibouAir sensors, read real-time data, and use that data to control a servo motor.
The complete source code is available for developers to explore, modify, and integrate into their own projects. Whether you’re building sensor monitoring systems, automation solutions, or custom IoT applications, this example provides a starting point for using BleuIO with compatible development boards.
In this tutorial, we will build a simple BLE-to-cloud air quality gateway using HibouAir, BleuIO, Python, Cloudflare Workers, and Cloudflare D1.
A HibouAir sensor will advertise its air quality measurements over Bluetooth Low Energy. BleuIO, connected to a computer through USB, will scan for a specific HibouAir device and provide the BLE advertising data to a Python application through the serial port. The Python application will decode CO2, temperature, and humidity, display the measurements in the terminal, and upload them to a Cloudflare Worker. The Worker will then store the measurements in a Cloudflare D1 database.
This project is intentionally kept simple. It demonstrates how BleuIO can act as the Bluetooth interface for a desktop or gateway application without requiring the application itself to manage a Bluetooth stack.
Why Cloudflare D1?
Cloudflare D1 is a serverless SQL database built on SQLite. It works particularly well with Cloudflare Workers, allowing us to create a small HTTP API without running our own server.
For a project like this, there are several advantages:
No database server to install or maintain
No local web server required
HTTPS is handled automatically
Cloudflare Workers can communicate directly with D1
D1 supports regular SQL
A useful free tier is available
The database remains accessible even when the Computer running the BLE gateway is offline
This makes it convenient for prototypes, BLE gateways, environmental monitoring projects, demonstrations, and small IoT applications.
For this example, the Computer only needs to run the Python gateway application. Everything after the HTTP request is handled in the cloud.
From the Cloudflare dashboard, go to the D1 database section and create a new database.
For this tutorial, we will call it:
hibouair-db
Once the database has been created, open its SQL Console.
Run the following SQL:
CREATE TABLE IF NOT EXISTS readings (
id INTEGER PRIMARY KEY AUTOINCREMENT,
board_id TEXT NOT NULL,
measured_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
co2 INTEGER NOT NULL,
temperature REAL NOT NULL,
humidity REAL NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_readings_board_time
ON readings(board_id, measured_at);
This creates a simple table containing:
Database ID
HibouAir board ID
Timestamp
CO₂
Temperature
Humidity
The measured_at field is generated automatically by D1 when the reading is inserted.
A stored record will look conceptually like this:
id 1
board_id 220069
measured_at 2026-10-05 14:42:30
co2 623
temperature 24.1
humidity 43.7
Step 2: Create the Cloudflare Worker
Next, create a Cloudflare Worker.
Now go to:
Workers & Pages → Create application
Create a basic Worker. ( you can choose “Start with Hello world”)
The Worker will sit between our Python application and the D1 database.
For this project, we can name it:
hibouair-api
and then press deploy.
After creating the Worker, open the code editor and replace the default code with the following :
Enter the same secret that was configured in the Cloudflare Worker:
CLOUDFLARE_API_KEY=YOUR_REAL_API_KEY
The info.txt file should not be committed to GitHub because it contains the API key.
Step 9: How the HibouAir Data Is Read
BleuIO communicates with our Python application using simple AT commands over the serial port.
The application first connects to BleuIO and places it in central mode.
It then searches for our HibouAir board ID using:
AT+FINDSCANDATA=220069=5
Here:
220069
is the HibouAir board ID, and:
5
defines the scan duration.
BleuIO handles the Bluetooth Low Energy scanning and returns the matching BLE advertising information over serial.
This means the Python application does not need to directly communicate with the operating system’s native Bluetooth API.
BleuIO then returns the advertising data to Python.
Step 10: Decode the HibouAir Advertisement
The Python application searches the advertising payload for the HibouAir data section:
5B070
For the HibouAir advertisement used in this example, the application extracts the three measurements needed for this project. Temperature, Humidity and CO2. The result becomes a normal Python structure similar to:
The Cloudflare Worker validates the key and inserts the measurement into D1.
The Python application therefore never connects directly to the database.
Step 12: Run the Application
Before running the project, make sure no other program is currently using the BleuIO serial port.
For example, close any active BleuIO connection in:
BleuIO application
screen
serial monitor
terminal program
other Python application
Then run:
python3 main.py
The application should connect to BleuIO.
You should see output similar to:
BleuIO + HibouAir + Cloudflare D1
---------------------------------
BleuIO port : /dev/cu.usbmodem4048FDEBA6D01
HibouAir ID : 220069
Scan interval: 30 seconds
Trying BleuIO on /dev/cu.usbmodem4048FDEBA6D01 at 115200 baud...
BleuIO connected successfully.
Setting BleuIO to central mode...
Ready.
The application will then start scanning:
Scanning for HibouAir 220069...
Command: AT+FINDSCANDATA=220069=5
When a valid HibouAir advertisement is received and decoded, the terminal will display something similar to:
============================================
HIBOUAIR AIR QUALITY
============================================
CO2 623 ppm
Temperature 24.1 °C
Humidity 43.7 %RH
============================================
Uploading to Cloudflare D1...
✓ Reading stored successfully.
Next scan in 23 seconds...
The application continues running automatically.
There is no need to restart it for each measurement.
To stop the application, press:
Ctrl + C
Step 13: Check the Data in Cloudflare D1
Now return to the Cloudflare D1 database console.
Run:
SELECT *
FROM readings
ORDER BY id DESC
LIMIT 10;
You should see the measurements coming from HibouAir.
For example:
id board_id measured_at co2 temperature humidity
12 220069 2026-10-05 14:58:20 618 24.1 43.8
11 220069 2026-10-05 14:57:50 621 24.1 43.8
10 220069 2026-10-05 14:57:20 623 24.1 43.7
This tutorial intentionally stops at the database and API level.
The objective is to demonstrate the complete BLE-to-cloud data path while keeping the example easy to understand.
At this point, the data is already available in the cloud.
A developer could later build a dashboard showing:
Current CO₂
Current Temperature
Current Humidity
CO₂ history
Temperature history
Humidity history
A dashboard could request historical readings through additional Worker API endpoints.
It could also display thresholds, warnings, averages, minimum/maximum measurements, or other analytics.
Those features are deliberately outside the scope of this example because the main goal is to demonstrate how easily BLE data can be brought into a serverless cloud architecture using BleuIO.
We kept the project intentionally simple so that the individual parts are easy to understand and modify.
From here, the project can be expanded in many directions. Multiple HibouAir sensors could be monitored, additional air quality parameters could be stored, historical API endpoints could be created, and a complete cloud dashboard could be built on top of the existing data.
In this project, we will look at how the BleuIO SSD025 Bluetooth Low Energy USB dongle can add BLE communication to an Adafruit Fruit Jam powered by the RP2350.
The project takes an unusual software approach. Instead of running the HibouAir scanner as part of the native firmware, the Fruit Jam runs a custom real-time operating system called myRTOS .
A myRTOS application module, hibouair.c, written in C, communicates with the BleuIO dongle over USB, scans for nearby HibouAir air-quality sensors, decodes their Bluetooth Low Energy advertisements and displays the latest measurements in real time in a terminal window.
The result is a compact embedded BLE air-quality gateway running on the RP2350.
The Fruit Jam is particularly suitable for this project because it has a built-in USB hub with two exposed USB host ports.
What does this project do?
1. HibouAir broadcasts sensor data
2. BleuIO receives the BLE advertisements
3. Fruit Jam receives the data over USB
4. myRTOS decodes and displays the measurements
The HibouAir sensor periodically broadcasts its measurements using BLE advertising packets. The SSD025 receives these packets and makes the information available to the RP2350 over USB.
The myRTOS application then scans for HibouAir devices, interprets the received information and maintains a live list of detected sensors.
The terminal provides an easy way to observe the air-quality information as it arrives.
Hardware
The project is built around three main pieces of hardware.
Adafruit Fruit Jam with the BleuIO SSD025 connected directly to the USB Type-A host port.
Adafruit Fruit Jam
The Fruit Jam is a compact computer based on the RP2350B microcontroller. Adafruit provides two USB Type-A host ports through an onboard USB hub, making it possible to connect USB peripherals directly to the board.
The board provides considerably more functionality than is required for this simple gateway. In addition to the RP2350B, it includes flash storage, PSRAM, USB host capability, microSD, DVI output, audio hardware and an ESP32-C6 for wireless connectivity.
For this project, however, the important feature is the USB host interface .
BleuIO SSD025
The BleuIO SSD025 is used as the Bluetooth Low Energy interface.
This means the RP2350 application does not need to implement the Bluetooth Low Energy stack itself.
The dongle supports Bluetooth 5.2 and USB Full Speed, can operate in Bluetooth central or peripheral roles, and is controlled through its USB interface.
The application can therefore access BLE functionality through BleuIO’s USB interface while leaving the Bluetooth communication to the dongle.
HibouAir SSD002
The HibouAir SSD002 is the wireless air-quality sensor.
HibouAir’s documentation describes the SSD002/2B as a CO2 air-quality monitor using an NDIR CO2 sensor, with wireless Bluetooth connectivity. The sensor family can provide environmental parameters including CO2, temperature, humidity, particulate matter and VOC-related measurements depending on the model.
Connect the board: Connect the Adafruit Fruit Jam to your computer using a USB-C cable and turn the power switch ON.
Hold down Button #1 (the UF2 BOOT button located on GPIO0), press and release the reset button while continuing to hold Button #1, and release Button #1 only after the bootloader drive appears.
Drag the project’s .uf2 file onto the board’s bootloader drive. The image includes myRTOS and the hibouair.c application module.
Press the reset button to reboot the board.
Connect the BleuIO SSD025: Plug the BleuIO SSD025 into one of the Fruit Jam’s USB Type-A host ports.
Power the HibouAir sensor: Make sure one or more HibouAir sensors are powered on and within Bluetooth range of the BleuIO dongle.
Button Locations on the Adafruit Fruit Jam
To enter UF2 bootloader mode, this project uses two buttons on the Fruit Jam:
Button #1 (UF2 BOOT) — located on GPIO0 towards the bottom-right edge of the board.
Reset button — located on the left edge of the board.
The image below shows the location of both buttons.
After rebooting, open a terminal window and connect to the board.
Windows
After rebooting, open Device Manager and identify the COM port assigned to the Fruit Jam. Connect to this port using a serial terminal such as PuTTY.
macOS
To find the Fruit Jam’s serial port, open a terminal and run:
ls /dev/cu.usbmodem*
The command should return a device similar to:
/dev/cu.usbmodem2351xxxx
Connect to it using:
screen /dev/cu.usbmodem2351xxxx
Real-Time HibouAir Scanning
After connecting to the Fruit Jam, start the HibouAir application from the myRTOS command interface:
myrtos:/> hibouair
scanning; ctrl-C to stop
The program then prints a table containing the detected HibouAir devices.
This gives the user an immediate overview of all the HibouAir sensors currently being received.
Expected Output
For example, the output below shows several HibouAir devices detected during a scan. The table shows each detected device’s board identifier, Bluetooth address, sensor type and latest environmental measurements.
Where Could This Go Next?
The current application concentrates on the essential task: receiving HibouAir advertisements and presenting the decoded measurements in real time.
Logging the data to the Fruit Jam’s microSD card would also make it possible to create long-term air-quality datasets without requiring a permanently connected computer.
The Fruit Jam’s USB host capability, microSD storage and RP2350B processor make this type of expansion practical.
Conclusion
This project demonstrates how the Adafruit Fruit Jam, BleuIO SSD025 and HibouAir SSD002 can be combined to create a compact RP2350-based Bluetooth Low Energy air-quality gateway.
HibouAir sensors broadcast their environmental measurements over BLE. BleuIO receives these advertisements and transfers the data to the Fruit Jam over USB, where the myRTOS hibouair application decodes the sensor data and presents the latest measurements in real time.
The project shows how BleuIO can add BLE communication to an RP2350-based embedded system while keeping the Bluetooth interface separate from the main application.
We’ve released BleuIO Pro firmware v1.0.7.1, bringing an important fix for applications that use Bluetooth Low Energy Extended Advertising.
What’s Fixed
This release resolves an issue affecting custom extended advertising instances after a connection-disconnection cycle.
In some cases, restarting a custom extended advertising instance could either fall back to the default legacy advertising mode or fail to restart altogether.
With v1.0.7.1, custom extended advertising now resumes correctly after a disconnect, making the behavior more reliable for applications that depend on repeated connection and advertising cycles.
How to Update Your Firmware
Updating your BleuIO Pro is straightforward.
You can download the latest firmware and follow the step-by-step update instructions in our official documentation:
Novel Bits recently published an interesting article, “Testing a Bluetooth LE Device Without a Phone,” featuring BleuIO in a practical Bluetooth Low Energy testing workflow.
Novel Bits is also our US distributor, and it was great to see BleuIO used in an example that highlights a different approach to BLE development and testing.
In the article, Mohammad Afaneh discusses where smartphone-based testing works well and where a more scriptable approach can be useful. Using BleuIO, he demonstrates how Bluetooth LE operations such as scanning, advertising, connecting, and disconnecting can be controlled directly from a terminal.
This is one of the useful aspects of BleuIO’s design. BleuIO connects over USB and can be controlled using simple AT commands, making it possible to interact with Bluetooth LE from a terminal, application, or script.
For developers, this can be useful for prototyping, repeatable testing, automation, and other situations where direct programmatic control of Bluetooth LE is preferred over manually interacting with a mobile application.
The Novel Bits article includes practical examples using BleuIO dongles and explains the approach in much more detail.
Air quality and environmental monitoring are common IoT use cases where Bluetooth Low Energy sensors can provide useful real-time information without requiring complex infrastructure.
In this project, we will use HibouAir as our air quality monitoring sensor, BleuIO as the Bluetooth Low Energy interface, and a Python application to collect and decode the advertised sensor data. The decoded measurements will then be sent to TagoIO, where we can store and visualize the data using an online dashboard.
The goal is to keep the project simple. There is no need to install an IoT server, MQTT broker, database, or dashboard software locally. BleuIO handles the BLE communication, the Python application processes the sensor data collected from HibouAir, and TagoIO handles the cloud side.
Why TagoIO?
TagoIO is an IoT platform that provides tools for connecting devices, storing sensor data, and creating dashboards for visualization.
For this project, one of the main reasons for choosing TagoIO is that it is easy to get started. It provides a free plan, which is suitable for experimenting with a small number of devices and building proof-of-concept IoT applications.
This makes it particularly useful for projects such as environmental monitoring where we simply want to send sensor measurements to the cloud and visualize them without setting up our own backend infrastructure.
If the project grows later, TagoIO also provides paid subscription options with additional resources and capabilities. This means we can start with the free option while developing and testing the project, and move to a larger plan later if necessary.
Another useful feature is its dashboard builder. Once our sensor variables reach TagoIO, we can create cards, displays, gauges, and time-series charts directly from the web interface.
For our HibouAir project, this allows us to visualize measurements such as:
Temperature
Relative humidity
CO2
Project Requirements
For this project, we need the following hardware and software.
BleuIO + HibouAir + TagoIO
==========================
BleuIO port: /dev/cu.usbmodem4048FDE52CF21
BleuIO responded OK
Looking for HibouAir 220069
When a valid HibouAir advertisement is received, the decoded sensor measurements will be displayed:
----------------------------------
HibouAir detected
----------------------------------
Temperature : 24.6 °C
Humidity : 48.2 %
CO2 : 612 ppm
----------------------------------
TagoIO upload: OK
The application will continue scanning and uploading new readings until it is stopped.
Use:
Ctrl + C
to stop the application.
Output
After the application has been running for a while, the sensor measurements will be available from the TagoIO device page and dashboard.
The dashboard can display the latest HibouAir measurements as well as their historical changes.
In this project, we created a simple cloud-connected environmental monitoring system using HibouAir, BleuIO, Python, and TagoIO.
This project should be considered a starting point rather than a finished monitoring product.
The code can be modified or expanded in many ways. Feel free to modify, extend, or reuse the code in your own BLE and IoT applications as needed.