BLE.connect automatically enables peripheral notifications as central device, why?

argon
Tags: #<Tag:0x00007fe225eeb330>

#1

I’m using an Argon (deviceOS 1.4.0) acting as a BLE central device to connect to a peripheral.

On each of the peripheral device characteristics that have NOTIFY it appears that the BLE.connect function is enabling these notifications.

Our device expects a command sequence on another characteristic before enabling notifications. We have 3 services with NOTIFY capability but generally only one service is used during a connection.

Is there a way to change this undesired behavior and selectively enable/disable Notifications?

Thanks!


#2

Hi @longtrail,

Sorry for the delayed response. I was on vacation and just came back to work.

The initial intention of automatically discovering and enabling notification is to simplify the development experience. But we also provide an option for user to manually do this stuff, see: https://docs.particle.io/reference/device-os/firmware/argon/#ble-connect-. If you specify the last argument automatic to be false, then it will only connect to peer device without going further, which means that you need to manually call peer.discoverAllCharacteristics() to discover all characteristics and characteristics.subscribe() to enable the characteristic’s notification.

We currently haven’t provided an API to automatically discover services and characteristics, while not enabling notifications.

Best regards,
Guohui


#3

Guohui,

Thanks for the response. I eventually dug into the BLE.connect() code and found the automatic flag. I was able to set automatic to false but only after changing the prototype in the header to not set ‘automatic = true’. I then did as you suggest to discover and subscribe to the specific notification of interest.

I think it is better to let the implementor to decide whether to do discovery and enable specific notifications upon connection. Power consumption on a battery operated device can be impacted by doing discovery and turning on all indications/notifications.

thanks again.

// PROTOTYPE BlePeerDevice connect(const BleAddress& addr, bool automatic = true) const; BlePeerDevice connect(const BleAddress& addr, const BleConnectionParams* params, bool automatic = true) const; BlePeerDevice connect(const BleAddress& addr, uint16_t interval, uint16_t latency, uint16_t timeout, bool automatic = true) const;


#4

I don’t think you have to modify the prototype declared in the header file. You can simply override the default automatic value by specifying it explicitly as like BLE.connect(..., false).


#5

I agree, but when I did that I got a compiler error. I can reproduce tomorrow and send the output.


#6

Here is the error that I get:

projects/lsgw-aws/src/lsgw-aws.ino:430:70: error: call of overloaded ‘connect(particle::BleAddress&, int)’ is ambiguous
peer = BLE.connect(scanResults[ii].address, false);

To work around, changed spark_wiring_ble.h to remove the default value for automatic:

BlePeerDevice connect(const BleAddress& addr, const BleConnectionParams* params, bool automatic) const;

BlePeerDevice connect(const BleAddress&amp; addr, uint16_t interval, uint16_t latency, uint16_t timeout, bool automatic) const;

BlePeerDevice connect(const BleAddress&amp; addr, bool automatic) const;

#7

What is the GCC version are you using to compile the Device OS? I’m using 5.3.1 and no error encountered.


#8

The same, “gcc-arm@5.3.1”, using Particle Workbench on OSX

redrock-2:lsgw-aws rbeck$ /Users/rbeck/.particle/toolchains/gcc-arm/5.3.1/bin/arm-none-eabi-g++ --version
arm-none-eabi-g++ (GNU Tools for ARM Embedded Processors) 5.3.1 20160307 (release) [ARM/embedded-5-branch revision 234589]
Copyright © 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


#9

What is the candidate overload function did the compiler promote when this error encountered?


#10

/Users/rbeck/particle/projects/lsgw-aws/src/lsgw-aws.ino: In function ‘bool findBhwModule(String)’:
/Users/rbeck/particle/projects/lsgw-aws/src/lsgw-aws.ino:435:70: error: call of overloaded ‘connect(particle::BleAddress&, int)’ is ambiguous
peer = BLE.connect(scanResults[ii].address, false);
^
In file included from ./inc/application.h:56:0,
from /Users/rbeck/particle/projects/lsgw-aws/src/lsgw-aws.ino:4:
…/wiring/inc/spark_wiring_ble.h:598:19: note: candidate: particle::BlePeerDevice particle::BleLocalDevice::connect(const particle::BleAddress&, const particle::BleConnectionParams*, bool) const
BlePeerDevice connect(const BleAddress& addr, const BleConnectionParams* params, bool automatic = true) const;
^
…/wiring/inc/spark_wiring_ble.h:600:19: note: candidate: particle::BlePeerDevice particle::BleLocalDevice::connect(const particle::BleAddress&, bool) const
BlePeerDevice connect(const BleAddress& addr, bool automatic = true) const;
^
make[3]: *** […/build/target/user/platform-12-m/lsgw-aws/src/lsgw-aws.o] Error 1


#11

Compiling the following code on WebIDE didn’t produce any error:

void setup() {
    BleAddress addr("11:22:33:44:55:66");
    BlePeerDevice peer = BLE.connect(addr, false);
}

void loop() {

}

#12

Trying to narrow this down, I can successfully compile, as expected, until adding Arduino.h header

#include "Particle.h"
#include "Arduino.h"

void setup() {

    BleAddress addr("11:22:33:44:55:66");

    BlePeerDevice peer = BLE.connect(addr, false);

}

void loop() {

}

Output…

/Users/rbeck/particle/projects/ble-test/src/ble-test.ino: In function 'void setup()':
/Users/rbeck/particle/projects/ble-test/src/ble-test.ino:16:49: error: call of overloaded 'connect(particle::BleAddress&, int)' is ambiguous
     BlePeerDevice peer = BLE.connect(addr, false);
                                                 ^
In file included from ./inc/application.h:56:0,
                 from ./inc/Particle.h:5,
                 from /Users/rbeck/particle/projects/ble-test/src/ble-test.ino:10:
../wiring/inc/spark_wiring_ble.h:598:19: note: candidate: particle::BlePeerDevice particle::BleLocalDevice::connect(const particle::BleAddress&, const particle::BleConnectionParams*, bool) const
     BlePeerDevice connect(const BleAddress& addr, const BleConnectionParams* params, bool automatic = true) const;
                   ^
../wiring/inc/spark_wiring_ble.h:600:19: note: candidate: particle::BlePeerDevice particle::BleLocalDevice::connect(const particle::BleAddress&, bool) const
     BlePeerDevice connect(const BleAddress& addr, bool automatic = true) const;
                   ^
make[2]: *** [../build/target/user/platform-12/ble-test/src/ble-test.o] Error 1

#13

So I think this is happening because spark_wiring_arduino_constants.h included by Arduino.h changes the definition of false from a boolean type to an integer, which results in connect(particle::BleAddress&, int) which is what the ambiguous message is all about.

#ifndef false
#define false       0x0
#endif

Is it possible for you to not include Arduino.h?

Edit:

If I cast false to a bool it compiles for me:

BlePeerDevice peer = BLE.connect(addr, (bool) false);

#14

Thanks for helping to isolate the source of the problem, I cast false to a (bool) as you suggested in BLE.connect and can compile clean. I’m using a number of libraries that require Arduino.h … I wonder if those true / false constants in spark_wiring_arduino_constants.h can be removed but I don’t know the Arduino history and why they are there. As a test, I commented them out of spark_wiring_arduino_constants.h and cleaned compile with the libraries I’m using and don’t need to cast false in the BLE.connect call.