WebBluetoothCG / web-bluetooth

Bluetooth support for the Web.
http://www.w3.org/community/web-bluetooth/
Other
1.39k stars 188 forks source link

When a BLE peripheral terminates a connection it should be possible to re-connect from the web app #192

Closed ketile closed 8 years ago

ketile commented 8 years ago

The following scenario is observed using a Nexus 5 and Chrome Dev for Android (48.0.2564.25):

  1. Discover Eddystone URL
  2. Open Eddystone URL
  3. Click Connect in web app
  4. Interact with BLE peripheral
  5. Connection is terminated by peripheral
  6. Click Connect in web app again. One of two things happens:
    • The device chooser fails to pop up
    • Chrome Dev crashes

When a connection is terminated by a peripheral it should be sufficient to click Connect in the web app in order to re-connect to the peripheral.

jyasskin commented 8 years ago

I think the spec already requires this, but there's likely a bug in Chrome. Can you file it at https://crbug.com/new?

g-ortuno commented 8 years ago

Thanks for the report! Do you have any code snippets that we can look at? Are you using the API directly or through a Polymer element?

I tried following the steps you described and I can't seem to be able to reproduce. When you say Click Connect in web app what does your "connect" function do?

ketile commented 8 years ago

Thank you for your replies.

@g-ortuno I've been using the Polymer platinum-bluetooth element. The code was from a codelab that seems to have been removed from code-labs.io. The only Web Bluetooth related codelab that is left is the PLAYBULB.

The function for the connect button:

  button.addEventListener('click', function() {
    console.log('Requesting a bluetooth device advertising custom 128-bit UUID service...');
    BLEDevice.request().then(function(device) {
      console.log('A bluetooth device has been found!');
      console.log('Device Name: ' + device.name);      
      // Necessary to avoid delay on first button press (Chromebook only)
      var characteristicData = BLEDevice.querySelector('platinum-bluetooth-characteristic');
      return characteristicData.read().then(function(value) {
        var data = new DataView(value);
        console.log('Custom characteristic value is ' + data.getUint8(0) );
      });
    })
    .catch(function(error) {
      console.error('Argh! ', error);
    });
  });

@jyasskin I will hold back on reporting this in case it is my code that is causing the issue.

beaufortfrancois commented 8 years ago

@ketile Polymer Bluetooth codelab is still there at https://www.code-labs.io/codelabs/polymer-bluetooth/#0 but not listed. I will file a bug for this.

ketile commented 8 years ago

@beaufortfrancois Thank you. Note that your link leads to a Spanish(?) version. Didn't see an option for changing the language.

beaufortfrancois commented 8 years ago

Can you provide a screenshot as I'm not able to reproduce this?

ketile commented 8 years ago

@beaufortfrancois codelab_in_spanish

g-ortuno commented 8 years ago

There are a couple of issues here:

  1. You are not seeing the chooser because the polymer element doesn't call requestDevice, which is what opens up the chooser, if you already granted permission to the device.
  2. The polymer element believes you are already connected. This is because we haven't fully implemented disconnection yet. We are working on it.
  3. Android doesn't handle disconnections yet. When a device disconnects, Chrome On Android still believes the device is connected and tries to access the characteristic. Still, I haven't been able to crash chrome.

All of that explains why nothings happens when you press connect.

Now, I haven't been able to reproduce the crash. Next time it happens make sure to report it. Then go to chrome://crashes and please file a bug.

device-2015-12-11-112440

beaufortfrancois commented 8 years ago

@ketile It should be fixed now. Can you confirm?

ketile commented 8 years ago

@g-ortuno Thank your for the detailed explanation. Do you have a rough estimate of when disconnection will be implemented? I'll make sure to report the crash if it happens again. Wasn´t aware of chrome://chrashes.

@beaufortfrancois I can confirm that the codelab now displays in English language. Thanks.

g-ortuno commented 8 years ago

Hard to tell. I'm currently working on it, but with the holiday break it will be delayed a bit.

perja12 commented 8 years ago

@g-ortuno I find the webbluetooth spec a bit unclear when it comes to disconnect. F.ex. should it be possible to call device.connectGATT() after a disconnect without calling requestDevice() first? Furthermore is states that " the UA MAY destroy device@[[representedDevice]]’s ATT Bearer" - is this the same as calling BluetoothGatt.java#close() or only BluetoothGatt.java#disconnect()? I found that only using disconnect will make the adapter stale after some time (at least on Nexus 5).

Another unclear section: "If the UA is currently connected to this device’s GATT server, gattServer provides a way to interact with it. While this device is disconnected, gattServer is null." But if gattServer is null, developers can't use the readonly attribute "connected" of BluetoothGATTRemoteServer.

g-ortuno commented 8 years ago
should it be possible to call device.connectGATT() after a disconnect without calling requestDevice() first?

Yes. resquestDevice allows the user of the website to give access to a device. Once the website has access to the device it can call connect/disconnect whenever it pleases.

Furthermore is states that " the UA MAY destroy device@[[representedDevice]]’s ATT Bearer" - is this the same as calling BluetoothGatt.java#close() or only BluetoothGatt.java#disconnect()?

It's the same as calling BluetoothGatt.java#disconnect(). I believe that BluetoothGatt.java#close() tells Android that the App is no longer interested in interacting with the device, which doesn't apply to this API.

I found that only using disconnect will make the adapter stale after some time (at least on Nexus 5).

Could you clarify what you mean here? What do you mean by "will make the adapter stale"?

"If the UA is currently connected to this device’s GATT server, gattServer provides a way to interact with it. While this device is disconnected, gattServer is null." But if gattServer is null, developers can't use the readonly attribute "connected" of BluetoothGATTRemoteServer.

We intend to unconditionally define gattServer to solve problems like this. There is a discussion on #181 that touches upon this. Feel free to suggest other options on that issue.

Thanks for the questions! In the future feel free to open issues about anything that you find unclear in the spec.

g-ortuno commented 8 years ago

@perja12 After discussing with the team it seems mapping BluetoothGatt.java#close() to "destroy device@[[representedDevice]]’s ATT Bearer" is the right thing to do.

perja12 commented 8 years ago

Thanks for the clarifications.

Regarding the stale adapter: what I meant was that after multiple connect and disconnect tries, I finally end up with not being able to use the Bluetooth adapter at all. In the log there is growing list like this:

01-12 13:12:45.956  2726  2872 W bt_btif : bta_gattc_conn_cback() - cif=3 connected=0 conn_id=3 reason=0x0016
01-12 13:12:45.957  2726  2872 W bt_btif : bta_gattc_conn_cback() - cif=4 connected=0 conn_id=4 reason=0x0016
01-12 13:12:45.957  2726  2872 W bt_btif : bta_gattc_conn_cback() - cif=5 connected=0 conn_id=5 reason=0x0016
01-12 13:12:45.957  2726  2872 W bt_btif : bta_gattc_conn_cback() - cif=6 connected=0 conn_id=6 reason=0x0016
01-12 13:12:45.957  2726  2872 W bt_btif : bta_gattc_conn_cback() - cif=7 connected=0 conn_id=7 reason=0x0016
01-12 13:12:45.957  2726  2872 W bt_btif : bta_gattc_conn_cback() - cif=8 connected=0 conn_id=8 reason=0x0016

In the end (when cif is 32) I'm getting this in the log:

01-12 13:13:00.280  2726  2872 E bt_btif : Register with GATT stack failed.

Then I can't connect to the peripheral anymore and other apps can't use the adapter either. This was just a small test I made and probably I'm not releasing the resource in the correct way. But when I used BluetoothGatt.java#close() this problem went away.

My test page: http://people.opera.com/perja/webbt/disconnect.html

g-ortuno commented 8 years ago

Ah yes this is a known issue. In theory you shouldn't need to worry about this. The problem is that our implementation is creating a new BluetoothGatt object every time you connect to the device (code in case you are interested), which is wrong. I opened an issue. Feel free to follow.