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:43] – ktokarz | en:edu:zmitac:s2:iotn:esp32ble4 [2024/04/01 20:08] (current) – [FAQ] ktokarz | ||
|---|---|---|---|
| Line 35: | Line 35: | ||
| </ | </ | ||
| + | Some global variables will be needed for our software. | ||
| + | < | ||
| + | // Variables | ||
| + | static boolean doConnect = false; | ||
| + | static boolean connected = false; | ||
| + | static boolean doScan = false; | ||
| + | static BLERemoteCharacteristic* pRemoteCharacteristic; | ||
| + | static BLEAdvertisedDevice* myDevice; | ||
| + | </ | ||
| + | Three callback functions will be defined. The first callback is for advertising. | ||
| < | < | ||
| - | // Create a BLE Characteristic | + | // Scan for BLE servers and find the first one that advertises |
| - | pNotifyCharacteristic = pService-> | + | // the service we are looking for. |
| - | | + | class MyAdvertisedDeviceCallbacks: |
| - | | + | void onResult(BLEAdvertisedDevice advertisedDevice) { |
| - | | + | // We have found a device, let's see if it contains the service we are looking for. |
| - | | + | if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(BLEUUID(SERVICE_UUID))) { |
| - | BLECharacteristic:: | + | |
| - | | + | |
| - | pNotifyCharacteristic->setValue(" | + | |
| - | // Create a BLE Descriptor | + | doConnect = true; |
| - | pNotifyCharacteristic-> | + | doScan = true; |
| + | |||
| + | } // Found our server | ||
| + | } // onResult | ||
| + | }; // MyAdvertisedDeviceCallbacks | ||
| </ | </ | ||
| + | Another callback will be executed on the notify event. In the example, we simply print incoming data to the console, but you can use the data in any other way. | ||
| + | < | ||
| + | static void notifyCallback( | ||
| + | BLERemoteCharacteristic* pBLERemoteCharacteristic, | ||
| + | uint8_t* pData, | ||
| + | size_t length, | ||
| + | bool isNotify) { | ||
| + | Serial.print(" | ||
| + | Serial.write(pData, | ||
| + | Serial.println(); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | 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) { | ||
| + | } | ||
| + | |||
| + | 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-> | ||
| + | } | ||
| + | </ | ||
| < | < | ||
| - | Any characteristic | + | 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; | ||
| + | } | ||
| - | After these modifications, it would be possible to observe an additional characteristic | + | 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 " | ||
| - | 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/ | ||
| - | <code c> | ||
| - | int int_value=0; | ||
| - | char text_value[] = " | ||
| - | </ | ||
| - | In the loop() function we modify the part executed if the connection was established. We'll add conversion from integer to text with atoi(), an update of characteristic value, and an incrementation of integer value. | ||
| < | < | ||
| - | void loop(){ | + | bool connectToServer() { |
| - | | + | |
| - | | + | |
| - | advStarted = true; | + | |
| - | } | + | |
| - | | + | |
| - | advStarted = false; | + | pClient-> |
| - | itoa(int_value, | + | |
| - | | + | pClient-> |
| - | | + | |
| - | | + | // Obtain a reference to the service we are after in the remote BLE server. |
| - | | + | BLERemoteService* pRemoteService = pClient->getService(BLEUUID(SERVICE_UUID)); |
| + | |||
| + | // Obtain a reference to the characteristic in the service of the remote BLE server. | ||
| + | pRemoteCharacteristic = pRemoteService->getCharacteristic(BLEUUID(REMOTE_CHARACTERISTIC_UUID)); | ||
| + | |||
| + | | ||
| + | pRemoteCharacteristic-> | ||
| - | | + | |
| - | }; | + | |
| + | } | ||
| </ | </ | ||
| + | |||
| + | < | ||
| + | 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.1711986215.txt.gz · Last modified: by ktokarz
