====== nRF52840 Zephyr BLE client ====== Usually, the BLE client role plays some user device eg. mobile phone, tablet or computer. In IoT systems sometimes BLE is used for M2M (machine-to-machine) data transmission. In such a situation an automatic BLE client must be implemented to connect to the peripherals and read the data eg. coming from BLE-capable sensors. BLE client must be configured to connect to the peripheral which exposes some specific service and characteristic. To do the lab exercise there is a need to create the peripheral device first. ===== BLE Health Temperature peripheral ===== The default Health Temperature example is sufficient to make the laboratory. How to import the project, flash, and execute is shown in {{https://dokuwiki.zmitac.aei.polsl.pl/en:edu:zmitac:s2:aih:lab:nrf52zephyrbleperipheral|peripheral example}}. ===== BLE central ==== Among the examples provided with Zephyr OS, there is also one complementary to the Health Temperature peripheral. It is named central_ht ((..\.platformio\packages\framework-zephyr\samples\bluetooth\central_ht)). The program is quite complex, here we will explain the most important elements and the process of establishing the connection.\\ The process of establishing and configuring a connection has a few steps: - scanning the neighbourhood to find connectable devices - comparing the advertising data to look for information on the required service - establishing the connection to peripheral - retrieving information on services and characteristics - subscribing to the interesting data with a notification or indication mechanism (optional) - reading data (by reading the characteristic value or automatically with notify/indicate) ==== Scanning the neighbourhood ==== In the main function, after the successful initialisation of the Bluetooth subsystem, scanning for nearby devices is started. err = bt_enable(NULL); ... err = scan_start(); ... The "scan_start()" function calls "bt_le_scan_start(&scan_param, device_found)" function. The second parameter is the callback function which processes scan results. ==== Searching advertising data for info on service ==== The "device_found()" function parses received advertising data with the "bt_data_parse()" function to the function "eir_found()". The latter function searches advertising data for the UUID of the Health Thermometer (0x1809). ==== Establishing the connection ==== After a successful search establishes a connection with the remote device by calling the function "bt_conn_le_create()".\\ Further processing is done by callback functions registered by the macro: BT_CONN_CB_DEFINE(conn_callbacks) = { .connected = connected, .disconnected = disconnected, }; Zephyr OS keeps the "bt_conn_cb" structure that allows the programmer to attach callback functions to chosen events. "BT_CONN_CB_DEFINE" macro attaches "connected" and "disconnected" functions to appropriate events. The "connected()" function is executed after successfully establishing the connection to the peripheral device. ==== Discovering the service ==== This function registers the callback function "discover_func()", and starts the discovery process by searching for the Health Thermometer service (UUID = 0x1809). ==== Searching for the characteristic ==== After finding this service discovery_func() is executed which performs further searching. First, it looks for the Temperature Measurement characteristic (UUID = 0x2a1c). ==== Subscribing to the data with indication ==== This characteristic should have the descriptor Client Characteristic Configuration (UUID = 0x1902) which makes it possible to enable notifications or indications. The indication enabling and registering the "notify_func()" as the callback for incoming indications finishes the establishing connection process.\\ ==== Ready! ==== Notice that after every successful discovery the function "discovery_func()" is called as the callback.\\ While the peripheral device updates the thermometer sensor reading, our central device receives this data and calls the "notify_func()" callback which prints the data using the UART port. ===== Tasks to do during the laboratory ===== - Create the Health Thermometer peripheral device and test if it operates properly - Import central device program "central_ht" (main.c and prj.conf files must be imported) - Compile and execute it observing its behaviour with and without peripheral running - Modify the peripheral code and central code to enable LED control on the central board with a button press on the peripheral board If you find problems with undefined BT_ATT_FIRST_ATTRIBUTE_HANDLE and BT_ATT_LAST_ATTRIBUTE_HANDLE define them as in the following code. #define BT_ATT_FIRST_ATTRIBUTE_HANDLE 0x0001 #define BT_ATT_LAST_ATTRIBUTE_HANDLE 0xFFFF To send simple binary data you can use a binary sensor service (UUID = 0x183B) with a binary sensor response characteristic (UUID = 0x2B2C).