Scan All Visible BLE Devices Example
1. Understanding the Script
This example demonstrates the process of scanning for and retrieving advertisement data from all visible devices.
1.1. Defines
Initially script creates numerous definitions, primarily intended to define the protocol structure. The first eight protocol definitions pertain to the packet header used by XG devices, which includes the MAC address, advertisement message type, and RSSI. For further details regarding the packet header, please refer to the function documentation: bt_adv_packet_read().
The rest of the data starting from ADV_DATA is no longer XG device header, but beacon data. Number of bytes will vary depending on what exactly Bluetooth device is advertising.
1.2. Initial Setup
The main function primarily performs the initial setup, including debug interface initialization, debug_print initialization, scan configuration and initialization.
To discover all visible devices, the BT_FILTER_MISMATCH option must be used, and no filters should be applied during the scan initialization procedure, as illustrated below:
main()
{
Init(RS232, RS232_SPEED, WORD_LENGTH, STOP_BITS, PARITY);
debug_init(RS232);
bt_init();
bt_scan_init(scan_parameters);
bt_scan_callback_enable(BT_FILTER_MISMATCH);
bt_scan_start();
for(;;)
{
Delay(100);
}
}1.3. Scan Data Callback
Immediately after the bt_scan_start function is invoked, the script begins scanning for Bluetooth devices within range. Once a device is detected, the BT_FILTER_MISMATCH callback is triggered, at which point the advertisement data is read and printed.
public callback (event)
{
switch(event)
{
case BT_FILTER_MISMATCH:
{
scan_data_length = bt_adv_packet_read(scanned_adv_data, BT_FILTER_MISMATCH);
debug_print("Device MAC: %02X:%02X:%02X:%02X:%02X:%02X, Device RSSI: %i dBm, RAW data: ",
scanned_adv_data[ADV_HEADER_MAC_BYTE_1], scanned_adv_data[ADV_HEADER_MAC_BYTE_2],
scanned_adv_data[ADV_HEADER_MAC_BYTE_3], scanned_adv_data[ADV_HEADER_MAC_BYTE_4],
scanned_adv_data[ADV_HEADER_MAC_BYTE_5], scanned_adv_data[ADV_HEADER_MAC_BYTE_6],
(0xFFFFFF00 | scanned_adv_data[ADV_HEADER_RSSI]));
for(new i = ADV_DATA; i < scan_data_length; i++)
{
debug_print("%02X ", scanned_adv_data[i]);
}
debug_print("\r\n");
}
}
return 0;
}1.4. Printed Data
The data output to the RS232 interface using the debug_print() function will appear as follows:
Device MAC: 2D:1B:57:DF:4F:EA, Device RSSI: -83 dBm, RAW data: 1E FF 06 00 01 09 20 22 F3 73 77 C5 CA FA 38 BA 63 C9 08 17 52 08 E2 18 6D 5C 2B 66 3B 27 D8 |
|---|
User can change scan type inside scan_parameters to either BT_SCAN_TYPE_ACTIVE or BT_SCAN_TYPE_PASSIVE to request response advertisement data or not.
2. Full Example Code
/*
* Script Name: Scan All Visible BLE Devices Example
* Version: 1.0.0
* Created: 2025-05-22
* Description: This script demonstrates how to configure scanner for scanning all visible ble beacons
* and prints RAW data via RS232.
* Usage:
* - To configure active or passive scanning user should edit scan_parameters.type.
* By default it's set to BT_SCAN_TYPE_ACTIVE.
* - To remove debug messages user should comment out or remove '#include <debug>'
* Prerequisites: Device firmware 01_131 or up. Auxiliary MCU firmware 2.1.7 or up.
* Changelog:
* 2025-05-22 (1.0.0):
*/
#include <io>
#include <read>
#include <float>
#include <string>
#include <core>
#include <write>
#include <define>
#include <socket>
#include <bluetooth>
#include <debug>
/** @brief Debug peripheral setup */
#define RS232_SPEED 115200
#define WORD_LENGTH WORDLENGTH_8
#define STOP_BITS STOPBITS_1
#define PARITY PARITY_NONE
/** @brief Scan data */
#define ADV_HEADER_MAC_BYTE_1 0
#define ADV_HEADER_MAC_BYTE_2 1
#define ADV_HEADER_MAC_BYTE_3 2
#define ADV_HEADER_MAC_BYTE_4 3
#define ADV_HEADER_MAC_BYTE_5 4
#define ADV_HEADER_MAC_BYTE_6 5
#define ADV_HEADER_ADV_TYPE 6
#define ADV_HEADER_RSSI 7
#define ADV_DATA 8
forward public callback (event);
new scan_parameters[.type, .options, .interval, .window, .timeout, .interval_coded, .window_coded] =
[
BT_SCAN_TYPE_ACTIVE, BT_ADV_OPT_NONE, BT_SCAN_INTERVAL_FAST, BT_SCAN_WINDOW_FAST, 0, 0, 0
];
new scan_data_length = 0;
new scanned_adv_data[255];
public callback (event)
{
switch(event)
{
case BT_FILTER_MISMATCH:
{
scan_data_length = bt_adv_packet_read(scanned_adv_data, BT_FILTER_MISMATCH);
debug_print("Device MAC: %02X:%02X:%02X:%02X:%02X:%02X, Device RSSI: %i dBm, RAW data: ",
scanned_adv_data[ADV_HEADER_MAC_BYTE_1], scanned_adv_data[ADV_HEADER_MAC_BYTE_2],
scanned_adv_data[ADV_HEADER_MAC_BYTE_3], scanned_adv_data[ADV_HEADER_MAC_BYTE_4],
scanned_adv_data[ADV_HEADER_MAC_BYTE_5], scanned_adv_data[ADV_HEADER_MAC_BYTE_6],
(0xFFFFFF00 | scanned_adv_data[ADV_HEADER_RSSI]));
for(new i = ADV_DATA; i < scan_data_length; i++)
{
debug_print("%02X ", scanned_adv_data[i]);
}
debug_print("\r\n");
}
}
return 0;
}
main()
{
Init(RS232, RS232_SPEED, WORD_LENGTH, STOP_BITS, PARITY);
debug_init(RS232);
bt_init();
bt_scan_init(scan_parameters);
bt_scan_callback_enable(BT_FILTER_MISMATCH);
bt_scan_start();
for(;;)
{
Delay(100);
}
}