This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| en:iot-open:practical:hardware:sut:stm32:iot_7 [2024/05/04 12:18] – created ktokarz | en:iot-open:practical:hardware:sut:stm32:iot_7 [2024/05/04 14:03] (current) – [STM_IoT_7: BLE Communication with notifications] ktokarz | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== STM_IoT_7: BLE Communication with indications ===== | ||
| + | This scenario presents how to extend the Bluetooth Low Energy server and client devices with a notification or indication mechanism for sending data automatically. If enabled, notifications or indications are sent at any time while the data in the server is updated. A difference between them is that a notification is an unacknowledged message while an indication is an acknowledged message. While one of them is enabled by the client, the server decides on the time of the message sent. | ||
| + | ===== Prerequisites ===== | ||
| + | It is necessary to understand the principles of the Bluetooth Low Energy protocol with concepts of services, characteristics and descriptors. We will use in this scenario the knowledge of the advertising process so making the [[en: | ||
| + | |||
| + | ===== Suggested Readings and Knowledge Resources ===== | ||
| + | * [[en: | ||
| + | * [[en: | ||
| + | * [[en: | ||
| + | |||
| + | ===== Hands-on Lab Scenario ===== | ||
| + | This scenario is intended to be implemented using two BLE laboratory nodes. One of them is a server, while the second is a client. Here we will present the extension of the scenario implemented in [[en: | ||
| + | < | ||
| + | The Nucleo STM32WB55 development boards which are used in our STM laboratory don't have the BLE firmware flashed by default. If you would like to test this scenario on your own board please refer to the STM documentation on the flashing process ((https:// | ||
| + | </ | ||
| + | |||
| + | ==== Task to be implemented ==== | ||
| + | **Task 1.** Implement a program that operates as the BLE server which advertises itself and allows us to connect to. We should be able to subscribe to indications of the characteristic. | ||
| + | \\ | ||
| + | **Task 2.** Implement a client device, capable of subscribing to the characteristic and reading the exemplary data from a server with a indication mechanism. | ||
| + | |||
| + | ==== Start ==== | ||
| + | It is advised to use the server and client programs from [[en: | ||
| + | |||
| + | ==== Steps ==== | ||
| + | We will pass through the lab in a few steps. We will add the second characteristic to the example from lab [[en: | ||
| + | |||
| + | === Step 1 === | ||
| + | We start with the program written during the laboratory [[en: | ||
| + | <code c> | ||
| + | #define INDICATE_CHARACTERISTIC_UUID " | ||
| + | |||
| + | // BLE Characteristic - custom 128-bit UUID, read and notify enabled | ||
| + | BLEByteCharacteristic pIndicateCharacteristic(INDICATE_CHARACTERISTIC_UUID, | ||
| + | </ | ||
| + | |||
| + | In the setup() function we add a new characteristic to the service and set its initial value. | ||
| + | < | ||
| + | // add the characteristic to the service | ||
| + | pService.addCharacteristic(pIndicateCharacteristic); | ||
| + | |||
| + | // set the initial value for the characteristic: | ||
| + | pIndicateCharacteristic.setValue(1); | ||
| + | </ | ||
| + | |||
| + | After these modifications, | ||
| + | |||
| + | === Step 2 === | ||
| + | At this step, we implement periodical data sending. We add the counter variable, an integer for holding the value incremented every loop pass. We will increment this counter with use of millis() function to do not block the loop() with delay(); | ||
| + | |||
| + | <code c> | ||
| + | int counter = 1; | ||
| + | int delay_millis; | ||
| + | </ | ||
| + | |||
| + | In the main loop() we implement the incrementation of the counter and updating of the characteristic. | ||
| + | <code c> | ||
| + | void loop() { | ||
| + | // listen for BLE peripherals to connect: | ||
| + | BLE.central(); | ||
| + | if (millis() > delay_millis +1000){ | ||
| + | delay_millis = millis(); | ||
| + | pIndicateCharacteristic.setValue(counter); | ||
| + | counter++; | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | === Step 3 === | ||
| + | In this step, we will analyse the behaviour of the client. The client software is much more complex than the server. It is because the server, called also the central device, in many circumstances is a more powerful device than the peripheral. Some parts of the software are implemented as callback functions because they handle reactions on the data coming asynchronously from the server. The diagram presents the algorithm of the client and data coming from the server. | ||
| + | {{ en: | ||
| + | |||
| + | === Step 4 === | ||
| + | While we have analysed the client' | ||
| + | <code c> | ||
| + | #define REMOTE_NOTIFY_CHARACTERISTIC_UUID " | ||
| + | </ | ||
| + | < | ||
| + | We intentionally specified here the same UUIDs as in ESP32 BLE scenarios. If both platforms are physically available in the same laboratory, you can try to connect different hardware platforms with BLE. | ||
| + | </ | ||
| + | |||
| + | In a loop() function we check if a peripheral with UUID we are interested in was discovered. If so we check its name. If the remote device' | ||
| + | < | ||
| + | At the time of writing this book the mechanism available for automatic update of the characteristic value was indication only. Notifications couldn' | ||
| + | </ | ||
| + | We will present the full code of the function to subscribe and receive the indications. The function reads the characteristic value in some steps: | ||
| + | - Connects to the remote device. | ||
| + | - Discovers attributes of the remote service. | ||
| + | - Retrieves the characteristic with specified UUID. | ||
| + | - Checks if the remote device is properly connected. | ||
| + | - Checks if the remote characteristic can be subscribed. | ||
| + | - Subscribes to the characteristic with indication mechanism. | ||
| + | - Waits for the characteristic value update. | ||
| + | - Reads the value and displays it on LCD. | ||
| + | |||
| + | <code c> | ||
| + | void display_characteristic(BLEDevice peripheral) { | ||
| + | | ||
| + | // connect to the peripheral | ||
| + | if (peripheral.connect()) { | ||
| + | | ||
| + | // discover peripheral attributes | ||
| + | if (peripheral.discoverAttributes()) { | ||
| + | | ||
| + | // retrieve the remote characteristic to read | ||
| + | remoteCharacteristic = peripheral.characteristic(REMOTE_NOTIFY_CHARACTERISTIC_UUID); | ||
| + | if (remoteCharacteristic) { | ||
| + | // check if the characteristic can be read | ||
| + | if (remoteCharacteristic.canSubscribe()){ | ||
| + | remoteCharacteristic.subscribe(); | ||
| + | | ||
| + | // if the peripheral is connected display the value | ||
| + | while (peripheral.connected()) { | ||
| + | | ||
| + | // check if the value was updated | ||
| + | if (remoteCharacteristic.valueUpdated()) { | ||
| + | | ||
| + | // yes, get the value, characteristic is 1 byte so use byte value | ||
| + | byte value = 0; | ||
| + | remoteCharacteristic.readValue(value); | ||
| + | lcd.setCursor(0, | ||
| + | lcd.print(value); | ||
| + | |||
| + | } // if (remoteCharacteristic.valueUpdated()) | ||
| + | } // while (peripheral.connected()) | ||
| + | } // if (remoteCharacteristic.canSubscribe()) | ||
| + | } // if (remoteCharacteristic) | ||
| + | peripheral.disconnect(); | ||
| + | } // if (peripheral.discoverAttributes()) | ||
| + | } // if (peripheral.connect()) | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== Result validation ==== | ||
| + | You should be able to read the name of the remote device in the first line of the LCD. After establishing the connection, the characteristic value should appear on the display' | ||
| + | |||
| + | ===== FAQ ===== | ||
| + | **What is the difference between notification and indication? | ||
| + | \\ | ||
| + | **Is the notification/ | ||
| + | |||
| + | <WRAP noprint> | ||
| + | ===== Project information ===== | ||
| + | {{: | ||
| + | This Intellectual Output was implemented under the Erasmus+ KA2.\\ | ||
| + | Project IOT-OPEN.EU Reloaded – Education-based strengthening of the European universities, | ||
| + | Project number: 2022-1-PL01-KA220-HED-000085090. | ||
| + | |||
| + | **__Erasmus+ Disclaimer__**\\ | ||
| + | This project has been funded with support from the European Commission. \\ | ||
| + | This publication reflects the views of only the author, and the Commission cannot be held responsible for any use that may be made of the information contained therein. | ||
| + | |||
| + | **__Copyright Notice__**\\ | ||
| + | This content was created by the IOT-OPEN.EU Reloaded consortium, 2022, | ||
| + | The content is Copyrighted and distributed under CC BY-NC [[https:// | ||
| + | <figure label> | ||
| + | {{: | ||
| + | </ | ||
| + | </ | ||