arduino-libraries / ArduinoBLE

ArduinoBLE library for Arduino
GNU Lesser General Public License v2.1
307 stars 205 forks source link

subscribe()/valueUpdated() not working #71

Open willtmakinen78 opened 4 years ago

willtmakinen78 commented 4 years ago

I've been using an Arduino Nano 33 BLE to communicate with my PC over the BlueFruit LE Friend's UART characteristic. Using the default ArduinoBLE library, I'm able to connect to the BlueFruit from the Nano33 as a central device, and write to the BlueFruit and have it show up in a serial terminal. I can get the Nano33 to read from the Bluefruit as well, by sending a Characteristic.read() request and a subsequent Charcterisitc.readValue() command. Subscribing to the rx characterisitic on the Nano33 is an issue, however, even though the Bluefruit's info page says that the rx characterisitc (address 0x0003) is capable of Notify. At first, Charcteristic.subscribe() would always return false, until I followed @gdsport's advice here and modified BLERemoteDescriptor.cpp. Now, although subscribe() returns true, Charcteristic.valueUpdated() always returns false, even when opening up a serial port to the BlueFruit and sending data with the UART service. This is the relevant Arduino code:

BLECharacteristic rxCharacteristic = peripheral.characteristic("6e400003-b5a3-f393-e0a9-e50e24dcca9e");

  // make sure BlueFruit UART characteristics have been loaded properly are of
  // proper format
  if (!rxCharacteristic) {
    Serial.println("Peripheral does not have RX characteristic!");
    peripheral.disconnect();
    return;
  } else if (!rxCharacteristic.canSubscribe()) {
    Serial.println("rxCharacteristic is not subscribable!");
    peripheral.disconnect();
    return;
  } else if (!rxCharacteristic.subscribe()) {
    Serial.println("rxCharacteristic subscription failed!");
    peripheral.disconnect();
    return;
  }
  Serial.println("subscribed");

  while (peripheral.connected()) {

      if (rxCharacteristic.valueUpdated()) {
        Serial.println("value updated");
      }
}

For reference, this is the modified code from BLERemoteDescriptor.cpp:

int BLERemoteDescriptor::writeValue(const uint8_t value[], int length)
{
  if (!ATT.connected(_connectionHandle)) {
    return false;
  }

  uint16_t maxLength = ATT.mtu(_connectionHandle) - 3;

  if (length > (int)maxLength) {
    // cap to MTU max length
    length = maxLength;
  }

  _value = (uint8_t*)realloc(_value, length);
  if (_value == NULL) {
    // realloc failed
    return 0;
  }  

#if 0
  uint8_t resp[4];
  int respLength = ATT.writeReq(_connectionHandle, _handle, value, length, resp);

  if (!respLength) {
    return 0;
  }

  if (resp[0] == 0x01) {
    // error
    return 0;
  }
#else 
    ATT.writeCmd(_connectionHandle, _handle, value, length);
#endif

  memcpy(_value, value, length);
  _valueLength = length;

  return 1;
}

Any thoughts on what might be causing this?

Arduino IDE version 1.8.12 and ArduinoBLE version 1.1.2

Gerriko commented 4 years ago

I had noticed the question raised about the failure to subscribe on the Arduino Forum and began to investigate.

For what it's worth, I discovered that within this function BLERemoteCharacteristic::writeCccd(uint16_t value) it determines the number of descriptors with this call int numDescriptors = descriptorCount();

For some reason the Bluefruit device is returning 0.

I ran the identical peripheral example using a BBC microbit and this correctly returns the value 2 (as in, there are two descriptors present for that characteristic 2901 and 2902).

willtmakinen78 commented 4 years ago

I ran the identical peripheral example using a BBC microbit and this correctly returns the value 2 (as in, there are two descriptors present for that characteristic 2901 and 2902).

So would you say that it's a Nano33 BLE issue? Also I'm assuming you were able to subscribe on the BBC microbit.

Gerriko commented 4 years ago

Yes, the Nano33 can subscribe to the BBC microbit as the Nano BLE central firmware can loop through the number of descriptors available from the BBC microbit and find 0x2902 to then apply the write value function. With Bluefruit, because number of descriptors is zero the Nano BLE central firmware bypasses and thus never updates the Bluefruit 0x2902.

willtmakinen78 commented 4 years ago

I see - any suggestions on how to fix the descriptorCount() function? Otherwise I'm going to order an ESP32 and be done with this :/.

Gerriko commented 4 years ago

I've discovered that this is not as straightforward as one might think.

I created a PSoC4 peripheral with the same GATT service + characteristics as the Bluefruit device but this time I did not implement the NOTIFY update functionality, just to see what happens (i.e. this should throw up an error).

The ESP32 returns that all is OK, when it should not have done so - so in this case the ESP32 would have crashed or not received any values from NOTIFY.

The nano BLE33 board (with ArduinoBLE library) interestingly finds the 2 descriptors (2901 and 2902) and says that it was able to update 2902 but then does not update the "fallback" option as the "if (_properties & (BLENotify | BLEIndicate))" was not true (with the Bluefruit device this was true but the cccd.writeValue must not return true for what ever reason).

if (_properties & (BLENotify | BLEIndicate)) { // no CCCD descriptor found, fallback to _valueHandle + 1 BLERemoteDescriptor cccd(NULL, 0, _connectionHandle, _valueHandle + 1); return cccd.writeValue((uint8_t*)&value, sizeof(value)); } Confirms the other post... as to what the real fix should be...

Gerriko commented 4 years ago

Debug using BLE.debug(Serial) - nano BLE connecting with Bluefruit:

Found f7:0f:7f:2d:4e:56 'Adafruit Bluefruit LE' 6e400001-b5a3-f393-e0a9-e50e24dcca9e HCI COMMAND TX -> 010C20020000 HCI EVENT RX <- 040E04010C2000 Connecting ... HCI COMMAND TX -> 010D2019600030000001564E2D7F0FF70006000C000000C80004000600 HCI EVENT RX <- 040F0400010D20 HCI EVENT RX <- 043E13010000000001564E2D7F0FF708000000C80007 Connected Discovering attributes ... HCI ACLDATA TX -> 02000007000300040002F700 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 020020070003000400031700 HCI ACLDATA TX -> 0200000B0007000400100100FFFF0028 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 02002012000E000400110601000700001808000B000118 HCI ACLDATA TX -> 0200000B0007000400100C00FFFF0028 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 0200201A001600040011140C00130023D1BCEA5F782315DEEF121230150000 HCI ACLDATA TX -> 0200000B0007000400101400FFFF0028 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 0200200C0008000400110614001E000A18 HCI ACLDATA TX -> 0200000B0007000400101F00FFFF0028 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 0200201A001600040011141F00FFFF9ECADC240EE5A9E093F3A3B50100406E HCI ACLDATA TX -> 0200000B000700040008010007000328 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 0200201B0017000400090702000A0300002A0400020500012A0600020700042A HCI ACLDATA TX -> 0200000B000700040008080007000328 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 0200200900050004000108080001 HCI ACLDATA TX -> 0200000B00070004000808000B000328 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 0200200D000900040009070900200A00052A HCI ACLDATA TX -> 0200000B0007000400080B000B000328 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 02002009000500040001080B000A HCI ACLDATA TX -> 0200000B0007000400080C0013000328 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 0200201B001700040009150D00040E0023D1BCEA5F782315DEEF121232150000 HCI ACLDATA TX -> 0200000B0007000400080F0013000328 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 0200201B001700040009150F0018100023D1BCEA5F782315DEEF121231150000 HCI ACLDATA TX -> 0200000B000700040008110013000328 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 0200201B00170004000915120002130023D1BCEA5F782315DEEF121234150000 HCI ACLDATA TX -> 0200000B000700040008140013000328 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 0200200900050004000108140001 HCI ACLDATA TX -> 0200000B00070004000814001E000328 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 0200201B001700040009071500021600292A1700021800242A1900021A00282A HCI ACLDATA TX -> 0200000B0007000400081B001E000328 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 02002014001000040009071B00021C00262A1D00021E00272A HCI ACLDATA TX -> 0200000B0007000400081F001E000328 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 02002009000500040001081F0001 HCI ACLDATA TX -> 0200000B0007000400081F00FFFF0328 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 0200201B0017000400091520001021009ECADC240EE5A9E093F3A3B50300406E HCI ACLDATA TX -> 0200000B0007000400082200FFFF0328 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 0200201B0017000400091524000C25009ECADC240EE5A9E093F3A3B50200406E HCI ACLDATA TX -> 0200000B0007000400082600FFFF0328 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 020020090005000400010826000A HCI ACLDATA TX -> 020000090005000400040B000B00 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 0200200A000600040005010B000229 HCI ACLDATA TX -> 020000090005000400040C000B00 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 02002009000500040001040C0001 HCI ACLDATA TX -> 020000090005000400042600FFFF HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 0200200A0006000400050126000129 HCI ACLDATA TX -> 020000090005000400042700FFFF HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 020020090005000400010427000A Attributes discovered --- Number descriptors found: 0 HCI ACLDATA TX -> 0200000900050004001222000100 HCI EVENT RX <- 0413050100000100 HCI ACLDATA RX <- 0200200900050004000112220003 --- writevalue.cccd returned: 0 Fail to subscribe... HCI ACLDATA RX <- 02002010000C000500120208001000200000002C01 HCI ACLDATA TX -> 0200000A0006000500130202000000 HCI COMMAND TX -> 0113200E00001000200000002C0104000600 HCI EVENT RX <- 0413050100000100 HCI EVENT RX <- 040F0400011320 HCI EVENT RX <- 043E0A03000000100000002C01

Gerriko commented 4 years ago

I've found that within the writeValue function (BLERemoteDescriptor), the Bluefruit has resp[0] = 0x01, which triggers an error condition. Not sure what this means though.

Trawling through that debug log I found that with the Bluefruit device we get: HCI ACLDATA TX -> 0200000900050004001222000100

and with the BBC microbit device we get: HCI ACLDATA TX -> 0200000900050004001213000100

willtmakinen78 commented 4 years ago

Alright, so it seems that my issues are a combination of BlueFruit and ArduinoBLE incompatabilities. Debugging the library is unfortunately a bit past the scope of project, since it's due in a week. In general I would be interested in helping out however, so please let me know if there's anything you need me to do.

polldo commented 4 years ago

Hi @willtmakinen78 and @Gerriko , thanks a lot for detailing the issue. In particular to @Gerriko for trying many combinations and posting logs!
I should have found the problem with the library, you can check this out here https://github.com/arduino-libraries/ArduinoBLE/pull/99

Could you please try if this fix solves the issue? Thanks!

kitoheedong commented 2 years ago

I am having the same issue with Nano RP4020. Is there someone who's facing the same issue?