edrosten / libblepp

Modern clean C++ Bluetooth Low Energy on Linux without the Bluez DBUS API
Other
239 stars 62 forks source link

One more (complex) example #29

Closed greymfm closed 6 years ago

greymfm commented 6 years ago

Hi, excellent work! If you do not develop C++ every day, I found it difficult to start with the library to figure out how to make a sequence of BLE actions. Finally, I got something working. Maybe we can add this as another example? It's for a device that requires one byte to be sent (authentifcation) to actually start with notifications. This example shows how to:

  1. connect and scan for characteristics
  2. enable BLE notify for certain characteristic
  3. write one byte for another characteristic
  4. reconnect on disconnect

console output looks like:

BEL: connect
BLE: enable notify
BLE: auth
notify: 19 : D2 64 04 00 FF 00 FF 00 FF FF FF FF C2 31 DF 31 B0 31 19
Disconnect for reason Connection Closed.
BEL: connect
BLE: enable notify
BLE: auth
notify: 19 : D2 64 04 00 FF 00 FF 00 FF FF FF FF C2 31 DF 31 B0 31 19
Disconnect for reason Connection Closed.
BEL: connect
BLE: enable notify
BLE: auth
notify: 19 : D2 64 04 00 FF 00 FF 00 FF FF FF FF C3 31 DF 31 B0 31 19
Disconnect for reason Connection Closed.
BEL: connect
BLE: enable notify
BLE: auth
notify: 19 : D2 64 04 00 FF 00 FF 00 FF FF FF FF C3 31 DF 31 B0 31 19
Disconnect for reason Connection Closed.
#include <iostream>
#include <iomanip>
#include <blepp/blestatemachine.h>
#include <unistd.h>
#include <chrono>
using namespace std;
using namespace chrono;
using namespace BLEPP;

#define DEVICE_UUID    "F4:B8:5E:AF:2A:A0"
#define SERVICE_UUID   "0000fff0-0000-1000-8000-00805f9b34fb"
#define AUTH_UUID      "0000fff3-0000-1000-8000-00805f9b34fb"
#define DATA_UUID      "0000fff4-0000-1000-8000-00805f9b34fb"
#define AUTH_DATA      0xD2

BLEGATTStateMachine gatt;
bool connected = false;

int main(int argc, char **argv){
    //log_level = Info;     

    std::function<void(const PDUNotificationOrIndication&)> notify_cb = [&](const PDUNotificationOrIndication& n)
    {       
    printf("notify: %d : ", n.num_elements());    
    const uint8_t* d = n.value().first;
    for (int i=0; i < n.num_elements(); i++){
      printf("%02X ", d[i]);
    }
    printf("\n");       
    gatt.close();       
    };

    std::function<void()> cbNotify = [&gatt, &notify_cb](){
    for(auto& service: gatt.primary_services)
      if(service.uuid == UUID(SERVICE_UUID))    {
        for(auto& characteristic: service.characteristics){
          if(characteristic.uuid == UUID(DATA_UUID))
          {            
             printf("BLE: enable notify\n");
             characteristic.cb_notify_or_indicate = notify_cb;
             characteristic.set_notify_and_indicate(true, false);                                               
          }                    
        }
      }          

    gatt.read_and_process_next();

    for(auto& service: gatt.primary_services)
      if(service.uuid == UUID(SERVICE_UUID))    {
        for(auto& characteristic: service.characteristics){
          if(characteristic.uuid == UUID(AUTH_UUID))
          {
              //Send a 1 (you can also send longer chunks of data too)
              printf("BLE: auth\n");            
              characteristic.write_without_response = true;
              characteristic.write_request(uint8_t(AUTH_DATA));                                      
          }         
        }
      }              
    };

    gatt.cb_disconnected = [](BLEGATTStateMachine::Disconnect d)
    {
        cerr << "Disconnect for reason " << BLEGATTStateMachine::get_disconnect_string(d) << endl;          
    gatt.connect_blocking(DEVICE_UUID);
    };

    gatt.setup_standard_scan(cbNotify);  

    gatt.cb_disconnected = [](BLEGATTStateMachine::Disconnect d)
    {
        cerr << "Disconnect for reason " << BLEGATTStateMachine::get_disconnect_string(d) << endl;              
    connected = false;
    };

    gatt.setup_standard_scan(cbNotify);  

    //This is how to use the blocking interface. It is very simple.  
    for(;;){
    if (!connected){
      printf("BLE: connect\n");      
      try {     
        gatt.connect_blocking(DEVICE_UUID);
        connected = true;
      }  
      catch (...) {     
        printf("BLE: error connecting\n");
      }  
    }
        gatt.read_and_process_next();    
  }

}