No ACL setup yet! Denying access to everyone.
en:edu:zmitac:s2:iotn:esp32ble4
Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| en:edu:zmitac:s2:iotn:esp32ble4 [2024/04/01 13:59] – created ktokarz | en:edu:zmitac:s2:iotn:esp32ble4 [2024/04/01 20:08] (current) – [FAQ] ktokarz | ||
|---|---|---|---|
| Line 18: | Line 18: | ||
| === Step 1 === | === Step 1 === | ||
| - | We start with the program written during | + | In this step, we will analyse |
| - | ^ Descriptor UUID ^ Bits 1 and 0 ^ CCCD value ^ Function | + | {{ :en:edu:zmitac:s2:iotn:ble_client.drawio.svg |
| - | | 0x2902 | + | |
| - | | ::: | 01 | 1 | enable notification | + | === Step 2 === |
| - | | ::: | 10 | + | We start implementation with the libraries needed. |
| < | < | ||
| - | #include "BLE2902.h" | + | #include "Arduino.h" |
| + | #include " | ||
| </ | </ | ||
| - | Next, we add another characteristic to the service and variable required to hold the pointer to the characteristic | + | Next, we define |
| < | < | ||
| - | BLECharacteristic | + | // The remote service we wish to connect to. |
| - | # | + | #define SERVICE_UUID " |
| + | // The characteristic | ||
| + | # | ||
| </ | </ | ||
| - | We create an additional characteristic with reading, writing, notify and indicate enabled, and the initial text " | + | |
| + | Some global variables will be needed | ||
| < | < | ||
| - | // Create a BLE Characteristic | + | // Variables |
| - | pNotifyCharacteristic | + | static boolean doConnect |
| - | | + | static boolean connected = false; |
| - | | + | static boolean doScan = false; |
| - | BLECharacteristic:: | + | static BLERemoteCharacteristic* pRemoteCharacteristic; |
| - | BLECharacteristic:: | + | static BLEAdvertisedDevice* myDevice; |
| - | BLECharacteristic:: | + | |
| - | ); | + | |
| - | pNotifyCharacteristic-> | + | |
| - | // Create a BLE Descriptor | + | |
| - | pNotifyCharacteristic-> | + | |
| </ | </ | ||
| - | <note> | + | Three callback functions will be defined. The first callback is for advertising. |
| - | Any characteristic can be configured as notify or indicate enabled. We can enable this mechanism | + | <code> |
| - | </note> | + | // Scan for BLE servers and find the first one that advertises |
| + | // the service we are looking for. | ||
| + | class MyAdvertisedDeviceCallbacks: | ||
| + | void onResult(BLEAdvertisedDevice advertisedDevice) { | ||
| + | | ||
| + | if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(BLEUUID(SERVICE_UUID))) { | ||
| - | After these modifications, | + | BLEDevice:: |
| + | myDevice = new BLEAdvertisedDevice(advertisedDevice); | ||
| + | doConnect = true; | ||
| + | doScan = true; | ||
| - | === Step 2 === | + | } // Found our server |
| - | At this step, we implement periodical data sending. We add two variables, an integer for holding the value incremented every loop pass and a text value converted from an integer to be sent within the indication/notification packet. | + | |
| - | <code c> | + | }; // MyAdvertisedDeviceCallbacks |
| - | int int_value=0; | + | |
| - | char text_value[] = " | + | |
| </ | </ | ||
| - | In the loop() function we modify the part executed | + | |
| + | Another callback will be executed | ||
| < | < | ||
| - | void loop(){ | + | static |
| - | | + | BLERemoteCharacteristic* pBLERemoteCharacteristic, |
| - | | + | uint8_t* pData, |
| - | | + | size_t length, |
| - | } | + | bool isNotify) { |
| + | | ||
| + | | ||
| + | | ||
| + | } | ||
| + | </ | ||
| - | if (deviceConnected){ | + | The third callback class helps to inform the other parts of the program about the connection close. |
| - | | + | < |
| - | | + | class MyClientCallback : public BLEClientCallbacks { |
| - | | + | void onConnect(BLEClient* pclient) { |
| - | pNotifyCharacteristic-> | + | } |
| - | int_value++; | + | |
| - | } | + | |
| - | delay(500); | + | void onDisconnect(BLEClient* pclient) { |
| + | connected = false; | ||
| + | } | ||
| }; | }; | ||
| </ | </ | ||
| + | |||
| + | The setup function initialises the Bluetooth, registers the advertising callback function, and starts the scan to look for nearby devices. | ||
| + | < | ||
| + | void setup() { | ||
| + | Serial.begin(115200); | ||
| + | Serial.println(" | ||
| + | | ||
| + | // Initialise the Bluetooth | ||
| + | BLEDevice:: | ||
| + | |||
| + | // Retrieve the pointer to the scan module | ||
| + | BLEScan* pBLEScan = BLEDevice:: | ||
| + | | ||
| + | // Register callback for incoming advertising | ||
| + | pBLEScan-> | ||
| + | | ||
| + | // Start scan parameters with active scan mode | ||
| + | pBLEScan-> | ||
| + | pBLEScan-> | ||
| + | pBLEScan-> | ||
| + | | ||
| + | // Start the scan for 30 seconds | ||
| + | pBLEScan-> | ||
| + | } | ||
| + | </ | ||
| + | < | ||
| + | In the original example, the scan time is 5 seconds only. It can be too short to connect to a remote device, especially if there are other devices in the neighbourhood. | ||
| + | </ | ||
| + | In the loop function, we wait for the information that the server with the service UUID we were interested in was found. It is signalled with the use of " | ||
| + | < | ||
| + | void loop() { | ||
| + | if (doConnect == true) { | ||
| + | connectToServer(); | ||
| + | doConnect = false; | ||
| + | } | ||
| + | |||
| + | if (!connected) { | ||
| + | if(doScan){ | ||
| + | BLEDevice:: | ||
| + | } | ||
| + | delay(1000); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | The connection to the server is executed in some steps: | ||
| + | - Creation of the client object. | ||
| + | - Setting the callback class for handling disconnection. | ||
| + | - Connection to the remote device. | ||
| + | - Setting parameters of the connection. | ||
| + | - Getting the reference to the service. | ||
| + | - Getting the reference to the characteristic. | ||
| + | - Registering notification for the characteristic and setting the notify callback function. | ||
| + | - Informing the main program with the " | ||
| + | |||
| + | < | ||
| + | bool connectToServer() { | ||
| + | BLEClient* | ||
| + | pClient-> | ||
| + | |||
| + | // Connect to the remote BLE Server. | ||
| + | pClient-> | ||
| + | | ||
| + | pClient-> | ||
| + | | ||
| + | // Obtain a reference to the service we are after in the remote BLE server. | ||
| + | BLERemoteService* pRemoteService = pClient-> | ||
| + | | ||
| + | // Obtain a reference to the characteristic in the service of the remote BLE server. | ||
| + | pRemoteCharacteristic = pRemoteService-> | ||
| + | | ||
| + | if(pRemoteCharacteristic-> | ||
| + | pRemoteCharacteristic-> | ||
| + | |||
| + | connected = true; | ||
| + | return true; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | Because this example is quite complex, it's good to have messages sent by the program. The original example contains many messages printed at almost every step of the program' | ||
| + | </ | ||
| + | |||
| ==== Result validation ==== | ==== Result validation ==== | ||
| - | You should be able to find the device in the BLE neighbourhood. It should allow us to establish a connection, read the characteristic data and write a new value. After enabling | + | You should be able to find the server |
| ===== FAQ ===== | ===== FAQ ===== | ||
| - | **What is the difference between notification and indication?**: As it was mentioned in the beginning the notification is an unacknowledged message while an indication is an acknowledged message. It means that if the indication message remains unacknowledged, | + | **Can we connect to the same peripheral with more than one central device?**: No, it's not possible. The BLE standard allows only one connection for the peripheral device. It was defined to ensure that BLE will work on constrained devices with small memory. |
| - | **Is the notification/ | + | **May I use the data in another way than printing it on the console?**: Of course. |
| <WRAP noprint> | <WRAP noprint> | ||
en/edu/zmitac/s2/iotn/esp32ble4.1711972795.txt.gz · Last modified: by ktokarz
