1
votes

I have an iOS app which advertises itself successfully using a CBPeripheralManager. In a Chrome App, I have successfully discovered the device (hence obtaining its address).

I have added a service with a custom UUID to the peripheral manager. didAddService is called (after the peripheral manager is powered on), and so I assume that part is successful.

I call chrome.bluetoothLowEnergy.connect(device address) in the Chrome app. The callback function is called without issue, and so I believe the connection is successful. There is no function called within the app when the connection has occurred - should there be?

I then call chrome.bluetooth.getServices(device address) in the Chrome app. An array of services is returned, however the array is empty. I believe it should return an array of length 1, not 0.

Am I overlooking something? Why are no services being returned? Should any of the peripheralManager functions be called during these operations?

Connect code:

function connect(address) {

  /* Connect persistently to the device. */
  chrome.bluetoothLowEnergy.connect(address, {persistent: true}, function() {
    if(chrome.runtime.lastError) {

      /* If we click a green device, we get this. We should try and handle it
         earlier. e.g. by removing the listener, or instead using the click
         to disconnect the device. */
      if(chrome.runtime.lastError.message == 'Already connected')
        setDeviceConnected(address);

      /* Print error and exit. */
      console.log(chrome.runtime.lastError.message);
      return;
    }

    console.log('Successfully connected to ' + address);
    setDeviceConnected(address);
    // getDeviceService();
    getDeviceServices(address);
  });

  return true;
}

Get services code:

function getDeviceServices(address) {
  chrome.bluetoothLowEnergy.getServices(address, function(services) {
    console.log('services.length: ' + services.length);
  });
}

Peripheral setup code:

- (void)setupPeripheral {
  _serviceName = SERVICE_NAME;
  _serviceUUID = [CBUUID UUIDWithString:SERVICE_UUID_STRING];
  _characteristicUUID = [CBUUID UUIDWithString:CHARACTERISTIC_UUID_STRING];

  _peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];

  _characteristic = [[CBMutableCharacteristic alloc] initWithType:_characteristicUUID
                                                     properties:CBCharacteristicPropertyRead | CBCharacteristicPropertyNotify
                                                     value:nil
                                                     permissions:CBAttributePermissionsReadable];

  _service = [[CBMutableService alloc] initWithType:_serviceUUID primary:YES];
  _service.characteristics = @[_characteristic];


  NSLog(@"Peripheral set up");
}

Start advertising (add the service just before we start advertising):

/* Start advertising */
- (void)startAdvertising {
  NSLog(@"Starting advertising...");

  NSDictionary *advertisment = @{
                                 CBAdvertisementDataServiceUUIDsKey : @[self.serviceUUID],
                                 CBAdvertisementDataLocalNameKey: self.serviceName
                                 };
  [self addServices];
  [self.peripheralManager startAdvertising:advertisment];
}

Call to start advertising within didUpdateState:

/* Did update state */
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
  switch (peripheral.state) {
    case CBPeripheralManagerStatePoweredOn:
      NSLog(@"peripheralStateChange: Powered On");
      // When the bluetooth has turned on, start advertising.
      [self startAdvertising];
      break;

Update

On connecting to the peripheral app with OSX app LightBlue, an alert shows up on the app to request a pairing. Then LightBlue can read characteristics from the app. When connecting with the Chrome app, the pairing alert does not show up.

2
Where are you adding the service you created to your peripheral like peripheral.addservice(service)Bhavuk Jain
I add the service just before the peripheral manager starts advertising, see code snippet 4, [self addServices]. It is a simple function: [_peripheralManager addService:_service];louisdeb

2 Answers

1
votes

Having chatted to web-bluetooth developers at W3C, I have now been able to discover services from the device, by updating chrome from v51 to v52 (apparantly also v53 works).

However currently (though I am yet to try it out), reading characteristics is currently unsupported for OSX, as seen here.

(I have not yet looked into it but this may provide some options on how to overcome the issues described here.)

1
votes

I've ran into this problem myself. I've developed a simple app that scans for devices and their services, but all devices found always report back an empty array of services. I have this problem on both OsX and ChromeOS.

There's an exception to this: when the device has previously been paired, I was able to get the services array on ChromeOS. This is confusing to me, since nothing I've read anywhere says a device has to be manually paired first, and there's no programatic way to pair a device one discovered.

EDIT: Upgrading to Chrome 53 fixed the problem. The site linked in louisdeb's answer is related to web-bluetooth, not chrome.bluetooth, so characteristics may actually work.