Voting resources, early voting, and poll worker information - VOTE. ... Adafruit is open and shipping.
0

Bluefruit Object Method Callbacks
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Bluefruit Object Method Callbacks

by JoshySav on Tue Jan 28, 2020 6:02 am

I understand this is more of a C++ question than one specific to the bluefruit library.

Essentially I have a wrapper around the bluefruit object ( bleManager)

I want to be able to subscribe to the `connect`, `disconnect`, `notify` callback methods using methods defined in the bleManager.

Currently the only way I've got it to work is using static methods. But the issue is that I lose the context of my bleManager.

Would anyone have any suggestions on how I could implement this functionality ?

Thanks in advance!

JoshySav
 
Posts: 10
Joined: Mon Sep 14, 2015 11:36 am

Re: Bluefruit Object Method Callbacks

by adafruit_support_mike on Wed Jan 29, 2020 3:35 am

In general, you can solve that problem with IS-A relationships or HAS-A relationships.

For the IS-A relationship, you create a subclass of the object you want to wrap, override the methods where you want to add code, then have each overridden method call the superclass version of the method once it's done its own thing:

Code: Select all | TOGGLE FULL SIZE
#include <iostream>

class Foo {
      int value;
      
   public:
      Foo ( int v=0 ) {
         value = v;
      }
      void shout ( int n );
};

void Foo::shout ( int n ) {
   std::cout << "    this is Foo::shout()\n";
   std::cout << "    value = " << value << "\n";
   std::cout << "    parameter = " << n << "\n";
}

class wrap_Foo : public Foo {
   public:
      wrap_Foo ( int v=0 ) : Foo( v ) {
      }
      void shout( int n );
};

void wrap_Foo::shout ( int n ) {
   std::cout << "    this is wrap_Foo::shout()\n";
   std::cout << "    parameter = " << n << "\n";
   Foo::shout( n / 2 );
}

using namespace std;
int main(int argc, char *argv[]) {
   cout << "demonstrate the base class:\n";
   Foo* f = new Foo( 10 );
   f->shout( 5 );
   
   cout << "\n";
   
   cout << "demonstrate the wrapper class:\n";
   wrap_Foo* w = new wrap_Foo( 20 );
   w->shout( 10 );
}

/*   PRODUCES THE OUTPUT:

   demonstrate the base class:
      this is Foo::shout()
      value = 10
      parameter = 5

   demonstrate the wrapper class:
      this is wrap_Foo::shout()
      parameter = 10
      this is Foo::shout()
      value = 20
      parameter = 5

*/
The HAS-A relationship keeps an internal copy of the class you want to wrap, and defines methods with the same name that pass information through to the wrapped object:

Code: Select all | TOGGLE FULL SIZE
#include <iostream>

class Foo {     
   public:
      Foo ( int v=0 ) {
         value = v;
      }
      int value;
      void shout ( int n );
};

void Foo::shout (int n ) {
   std::cout << "    this is Foo::shout()\n";
   std::cout << "    value = " << value << "\n";
   std::cout << "    parameter = " << n << "\n";
}

class wrap_Foo {
   Foo* f;
   public:
      wrap_Foo ( int v=0 ) {
         f = new Foo( v );
      }
      void shout( int n );
};

void wrap_Foo::shout ( int n ) {
   std::cout << "    this is wrap_Foo::shout()\n";
   std::cout << "    the wrapped value is " << f->value << "\n";
   std::cout << "    parameter = " << n << "\n";
   f->shout( n / 2 );
}

using namespace std;
int main(int argc, char *argv[]) {
   cout << "demonstrate the base class:\n";
   Foo* f = new Foo( 10 );
   f->shout( 5 );
   
   cout << "\n";
   
   cout << "demonstrate the wrapper class:\n";
   wrap_Foo* w = new wrap_Foo( 20 );
   w->shout( 10 );
}

/*  PRODUCES THE OUTPUT:

   demonstrate the base class:
      this is Foo::shout()
      value = 10
      parameter = 5

   demonstrate the wrapper class:
      this is wrap_Foo::shout()
      the wrapped value is 20
      parameter = 10
      this is Foo::shout()
      value = 20
      parameter = 5

*/
The version you choose depends on the way you want to use the wrapper. The IS-A style is a convenient way to add behavior to an existing class if you can replace the object's initial creation. The HAS-A style works when you can create the wrapper around specific function calls.

adafruit_support_mike
 
Posts: 61443
Joined: Thu Feb 11, 2010 2:51 pm

Re: Bluefruit Object Method Callbacks

by JoshySav on Thu Jan 30, 2020 5:14 am

Thank you for taking the time to explain.

The issue I am having is that I want to add object method callbacks to the `BLEPeriph` object inside of `AdafruitBluefruit`. Currently the `BLEPeriph` has the following callbacks.

Code: Select all | TOGGLE FULL SIZE
void setConnectCallback   ( ble_connect_callback_t    fp);
void setDisconnectCallback( ble_disconnect_callback_t fp);


with the pointer types defined in `bluefruit_common.h`

Code: Select all | TOGGLE FULL SIZE
typedef void (*ble_connect_callback_t    ) (uint16_t conn_hdl);
typedef void (*ble_disconnect_callback_t ) (uint16_t conn_hdl, uint8_t reason);


As you suggested is there a way of overriding these callback methods in order to pass a object method callback?

I really don't know if I am over complicating this. But essentially I am using the Arduino platform and all the examples have the callbacks in the .ino file, but I am looking to add the callbacks to object.

JoshySav
 
Posts: 10
Joined: Mon Sep 14, 2015 11:36 am

Re: Bluefruit Object Method Callbacks

by adafruit_support_mike on Thu Jan 30, 2020 5:28 am

You can subclass (IS-A) the BLEPeriph object, add your own code to the overridden functions, and then tell the AdafruitBluefruit code to use your subclass instead of the original class.

adafruit_support_mike
 
Posts: 61443
Joined: Thu Feb 11, 2010 2:51 pm

Re: Bluefruit Object Method Callbacks

by JoshySav on Thu Jan 30, 2020 6:07 am

Thank you! Could you show me how I would override the connect callback?

JoshySav
 
Posts: 10
Joined: Mon Sep 14, 2015 11:36 am

Please be positive and constructive with your questions and comments.