Device-os: Xenon: Central BLE setValue does not update characteristic value

Created on 11 Sep 2019  路  13Comments  路  Source: particle-iot/device-os

Bug Report

Expected Behavior

Using a Xenon and a Nordic Thingy 52, the purpose of my exercise was to prove the Xenon in central mode can both read and write to a particular characteristic.

When connected, ledCharacteristic.getValue(buf, sizeof(buf)); should retrieve the contents of the register.

It should also be able to set the value of the characteristic using ledCharacteristic.setValue(buf, sizeof(buf));

(Where buf is uint8_t buf[4]; in this case)

Observed Behavior

ledCharacteristic.getValue works great. Returns the data as expected.

When the data is modified, say from 0x01ffffff to 0x0100ffff. And then passed to ledCharacteristic.setValue, it does not update accordingly.

To be specific I'm writing to the LED control characteristic: BleUuid("EF680301-9B35-4933-9B10-52FFA9740042"); When .properties() is run on the characteristic it returns 0xa (read and write, as expected)

Steps to Reproduce

Device OS 1.3.1
I was able to set the value using both nRF Connect and Light Blue explorer.

Test App

/*
 * Project bluetooth-scan-and-connect
 * Description:
 * Author:
 * Date:
 */

#include "Particle.h"

// For debugging only
SYSTEM_MODE(MANUAL);

// For logging
SerialLogHandler logHandler(115200, LOG_LEVEL_ERROR, {
    { "app", LOG_LEVEL_TRACE }, // enable all app messages
});

// Used in centra mode to track the thingy and the LED characteristic
const BleUuid thingyLedUUID = BleUuid("EF680301-9B35-4933-9B10-52FFA9740042");
BleAddress thingyAddress = BleAddress("ff:ff:ff:ff:ff:ff");
BlePeerDevice thingy;
BleCharacteristic ledCharacteristic;

// Callback when a new device is found advertising
void scanResultCallback(const BleScanResult *scanResult, void *context) {

  String name = scanResult->advertisingData.deviceName();

  // Return if the name does not equal what we're looking for
  if( name != "Thingy" ) return;

  // Set the address
  thingyAddress = scanResult->address;

  // Stop scanning
  BLE.stopScanning();

}

// setup() runs once, when the device is first turned on.
void setup() {
  (void)logHandler; // Does nothing, just to eliminate warning for unused variable
}

// loop() runs over and over again, as quickly as it can execute.
void loop() {
  // Check for scan start

  if( !thingy.connected() ) {
    if( !(thingyAddress == BleAddress("ff:ff:ff:ff:ff:ff")) ) {
      // Connect
      Log.trace("Connecting to Thingy..");
      thingy = BLE.connect(thingyAddress);
    } else {
      Log.trace("Scanning for Thingy..");
      BLE.scan(scanResultCallback, NULL);
    }

  } else {
    if( !ledCharacteristic.valid() ) {
      Log.trace("Characteristic not valid!");
      thingy.getCharacteristicByUUID(ledCharacteristic, thingyLedUUID);
    } else {
      // Get the properties
      // BleCharacteristicProperty prop = ledCharacteristic.properties();
      // Log.trace("Prop %x",(uint8_t)prop);

      // Get the value of the characteristic
      uint8_t buf[4];

      // Get the current value
      ledCharacteristic.getValue(buf, sizeof(buf));
      Log.trace("Buffer value %x %x %x %x", buf[0], buf[1], buf[2], buf[3] );

      // Iterate over all colors
      if( buf[1] == 0xff) {
        buf[1] = 0x00;
        buf[2] = 0xff;
      }else if( buf[2] == 0xff) {
        buf[2] = 0x00;
        buf[3] = 0xff;
      } else if( buf[3] == 0xff) {
        buf[3] = 0x00;
        buf[1] = 0xff;
      }

      // Output buffer value
      Log.trace("Buffer write value %x %x %x %x", buf[0], buf[1], buf[2], buf[3] );

      // Writing the value
      ledCharacteristic.setValue(buf, sizeof(buf));

    }
  }

  delay(1000);
}

References

None at this time.

bug confirmed ble realembedded-platform

All 13 comments

@jaredwolff Thanks for submitting an issue. Would you mind verifying whether the issue is still present in 1.4.0? 1.3.1 does not have our full BLE offering, and I think this particular issue has been resolved by https://github.com/particle-iot/device-os/pull/1901 in 1.4.0

@avtolstoy sounds good. I'll give it a shot and report back! 馃憤

Just gave it a shot with the same example code as above. No dice. 馃槶

Output from particle identify

Your system firmware version is 1.4.0

I also tried writing a single byte (0x00) to that characteristic. It should completely deactivate the LED but I'm not seeing any response. setValue doesn't add any extraneous padding does it? I know the Thingy52 firmware will reject the payload if it doesn't match.

:disappointed:

@XuGuohui Would you please take a look into this?

I'm right looking into this issue. Will post any finding here.

So running the Thingy52 with debug output. No matter what I send from the Xenon, it receives two bytes:

ble_uis       :INFO:data_length 2
ble_uis       :INFO:Data 0 0

Where I'm sending

ledCharacteristic.setValue(buf, sizeof(buf));

(buffer size in this case is 4)

I got it. We've missed the case that when the last argument of setValue() is equal to BleTxRxType::AUTO and the characteristic property includes BleCharacteristicProperty::WRITE, it will just return. See here: https://github.com/particle-iot/device-os/blob/develop/wiring/src/spark_wiring_ble.cpp#L1167. For now, by specifying the BleTxRxType to be ACK explicitly should fix this issue. @jaredwolff Could you help verify that?

EDIT: But it's weird that this shouldn't happen against 1.3.1.

@XuGuohui setting the BleTxRxType to BleTxRxType::ACK got it working!

Is the length of sent data correct?

Yes. The main payload seems correct.

I still do get the 2 0x00 bytes upon connection. Not sure what is generating that. They ultimately get discarded by the Thingy52 firmware.

Is this two bytes received over the ledCharacteristic?

@XuGuohui correct, I'm getting those bytes after the handle of the incoming data is compared to the LED handle.

Was this page helpful?
0 / 5 - 0 ratings