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.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| en:edu:zmitac:s2:iotn:esp32ble4 [2024/04/01 17:36] – 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 libraries needed. | + | 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 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. |
| + | {{ : | ||
| + | |||
| + | === Step 2 === | ||
| + | We start implementation | ||
| < | < | ||
| #include " | #include " | ||
| Line 30: | Line 34: | ||
| #define REMOTE_CHARACTERISTIC_UUID " | #define REMOTE_CHARACTERISTIC_UUID " | ||
| </ | </ | ||
| - | The client software is much more complex than the server. It is because the central device in many circumstances is a more powerful device than the peripheral. The diagram presents the algorithm of the client and data coming from the server. | ||
| - | {{ : | ||
| + | Some global variables will be needed for our software. | ||
| < | < | ||
| - | // 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.1711985807.txt.gz · Last modified: by ktokarz
