arduino / ArduinoCore-arc32

GNU Lesser General Public License v2.1
329 stars 284 forks source link

CurieBLE: characteristic.read() reports success when peripheral responds with error #516

Open sandeepmistry opened 7 years ago

sandeepmistry commented 7 years ago

Testing with the 2.0.1RC2.1 JSON:

Arduino sketch:

#include <CurieBLE.h>

void setup() {
  Serial.begin(9600);

  while (!Serial);

  Serial.println("BLE Central - Read + Write test");

  // initialize the BLE hardware
  BLE.begin();

  // start scanning for peripheral
  BLE.scanForName("rwfail");
}

void loop() {
 // check if a peripheral has been discovered
  BLEDevice peripheral = BLE.available();

  if (peripheral) {
    // discovered a peripheral, print out address, local name, and advertised service
    Serial.print("Found ");
    Serial.println(peripheral.address());

    BLE.stopScan();

    Serial.println("Connecting ...");
    if (peripheral.connect()) {
      Serial.println("Connected");
    } else {
      Serial.println("Failed to connect!");
      while(1);
    }

    // discover peripheral attributes
    Serial.println("Discovering attributes ...");
    if (peripheral.discoverAttributes()) {
      Serial.println("Attributes discovered");
    } else {
      Serial.println("Attribute discovery failed.");
      peripheral.disconnect();
      while(1);
    }

    BLECharacteristic c = peripheral.characteristic("fa12");

    while (peripheral.connected()) {
      Serial.println("reading ...");
      if (c.read()) {
        // should not happen
        Serial.println("read success");
      } else {
        // expected
        Serial.println("read fail");
      }

      Serial.println("writing ...");
      if (c.writeInt(42)) {
        // should not happen
        Serial.println("write success");
      } else {
        // expected
        Serial.println("write fail");
      }

      delay(1000);
    }

    BLE.scan();
  }
}

Node.js bleno test app:

var bleno = require('bleno');

var BlenoPrimaryService = bleno.PrimaryService;
var BlenoCharacteristic = bleno.Characteristic;

console.log('bleno - read + write fail');

bleno.on('stateChange', function(state) {
  console.log('on -> stateChange: ' + state);

  if (state === 'poweredOn') {
    bleno.startAdvertising('rwfail', ['fa11']);
  } else {
    bleno.stopAdvertising();
  }
});

bleno.on('advertisingStart', function(error) {
  console.log('on -> advertisingStart: ' + (error ? 'error ' + error : 'success'));

  if (!error) {
    bleno.setServices([
      new BlenoPrimaryService({
        uuid: 'fa11',
        characteristics: [
          new BlenoCharacteristic({
            uuid: 'fa12',
            properties: ['read', 'write'],
            onReadRequest: function(offset, callback) {
              console.log('onReadRequest');
              callback(BlenoCharacteristic.RESULT_UNLIKELY_ERROR);
            },
            onWriteRequest: function(data, offset, withoutResponse, callback) {
              console.log('onWriteRequest');
              callback(BlenoCharacteristic.RESULT_UNLIKELY_ERROR);
            }
          })
        ]
      })
    ]);
  }
});

characteristic.read() is return true even though the GATT read request fails. I expect it to return false to indicate failure.

Packet Logger trace:

screen shot 2017-03-29 at 12 47 43 pm
noelpaz commented 7 years ago

@sandeepmistry The bleno peripheral node.js app is returning as below. I do not see the string for RESULT_UNLIKELY_ERROR Doesn't this mean success? Anyway I will be also firing up our BLE sniffer and update or add another comment.


onWriteRequest
onReadRequest
onWriteRequest
noelpaz commented 7 years ago

@SidLeung It looks like it is confirmed, We are not reporting the error packet by the Peripheral

image

noelpaz commented 7 years ago

Issue516.zip

Analyzer files attached.

sandeepmistry commented 7 years ago

I do not see the string for RESULT_UNLIKELY_ERROR Doesn't this mean success?

@noelpaz in case it's not clear, RESULT_UNLIKELY_ERROR is a constant mapped to the GATT error code 0x0e.

Other bleno constants include:

Characteristic.RESULT_SUCCESS                  = Characteristic.prototype.RESULT_SUCCESS                  = 0x00;
Characteristic.RESULT_INVALID_OFFSET           = Characteristic.prototype.RESULT_INVALID_OFFSET           = 0x07;
Characteristic.RESULT_ATTR_NOT_LONG            = Characteristic.prototype.RESULT_ATTR_NOT_LONG            = 0x0b;
Characteristic.RESULT_INVALID_ATTRIBUTE_LENGTH = Characteristic.prototype.RESULT_INVALID_ATTRIBUTE_LENGTH = 0x0d;
Characteristic.RESULT_UNLIKELY_ERROR           = Characteristic.prototype.RESULT_UNLIKELY_ERROR           = 0x0e;