W3C home > Mailing lists > Public > public-web-bluetooth@w3.org > March 2016

Re: Should we expose all devices as if they were bonded?

From: François Beaufort 🇫🇷 <fbeaufort@google.com>
Date: Thu, 31 Mar 2016 14:47:57 +0000
Message-ID: <CAPpwU5KN7kz9t0gp_qUFHoOy7EexLKVtAWtbypgp78Uj2KhNZw@mail.gmail.com>
To: Jeffrey Yasskin <jyasskin@google.com>, "Von Dentz, Luiz" <luiz.von.dentz@intel.com>
Cc: Rob Moran <Rob.Moran@arm.com>, public-web-bluetooth <public-web-bluetooth@w3.org>, "Christiansen, Kenneth R" <kenneth.r.christiansen@intel.com>
What is the status on this?

On Fri, Mar 18, 2016 at 8:18 PM Jeffrey Yasskin <jyasskin@google.com> wrote:

> On Fri, Mar 18, 2016 at 7:57 AM, Von Dentz, Luiz
> <luiz.von.dentz@intel.com> wrote:
> > Hi Jeffrey,
> >
> > On Thu, Mar 17, 2016 at 11:00 PM, Jeffrey Yasskin <jyasskin@google.com>
> wrote:
> >> On Thu, Mar 17, 2016 at 10:12 AM, Rob Moran <Rob.Moran@arm.com> wrote:
> >>>
> >>> I agree that registering service changed events is the same in both
> cases,
> >>> but having to register for these across re-connects feels unintuitive
> versus
> >>> scanning after a re-connect.
> >>> I am assuming that discovering services again would still return the
> >>> cached ones, however.
> >>
> >>
> >> If we treat devices as not-bonded, I think we get:
> >>
> >>   await device.gatt.connect();
> >>   // Depends on
> https://github.com/WebBluetoothCG/web-bluetooth/issues/53:
> >>   device.addEventListener('servicechanged', change =>
> console.log(change));
> >>   let service = await device.gatt.getPrimaryService('uuid');
> >>   let characteristic = await service.getCharacteristic('uuid2');
> >>   device.gatt.disconnect();
> >>   await device.gatt.connect();
> >>   await service.getCharacteristic('uuid2') // Throws InvalidStateError:
> >> service no longer exists?
> >>   let service2 = await device.gatt.getPrimaryService('uuid'); // Waits
> until
> >> discovery process finishes.
> >>   service ?== service2; // ???
> >>   device.gatt.disconnect();
> >>   // 'uuid' service removed, replaced with 'uuid3' service.
> >>   await device.gatt.connect();
> >>   await service.getCharacteristic('uuid2') // Throws InvalidStateError:
> >> service no longer exists?
> >>   let service3 = await device.gatt.getPrimaryService('uuid'); //
> >> NotFoundError.
> >>   let service4 = await device.gatt.getPrimaryService('uuid3');
> >>   service4 !== service2;
> >>
> >> I think we wouldn't get any 'servicechanged' events in this scenario,
> since
> >> the changes happen when no services are known.
> >
> > Well if that would be the case 'servicechanged' cannot be used for
> > detecting new services since it appears to ignore any change outside
> > the known range.
>
> In the design I've got so far, to detect a service you expect to be
> added, you'd getPrimaryService('the-service'), catch the rejection if
> it's not there, and then watch for 'servicechanged' to tell you it's
> been added. Skipping the getPrimaryService() call could indeed cause
> the browser to skip the 'servicechanged' event because of the rules in
>
> https://webbluetoothcg.github.io/web-bluetooth/#only-notify-for-requested-services
> .
> Those are there so the browser doesn't have to do a full discovery on
> connect().
>
> >> If we treat devices as bonded, I think we get the following flow
> instead:
> >>
> >>   await device.gatt.connect();
> >>   // Depends on
> https://github.com/WebBluetoothCG/web-bluetooth/issues/53:
> >>   device.addEventListener('servicechanged', change => console.log);
> >>   let service = await device.gatt.getPrimaryService('uuid');
> >>   let characteristic = await service.getCharacteristic('uuid2');
> >>   let value = await characteristic.readValue();
> >>   device.gatt.disconnect();
> >>   await device.gatt.connect();
> >>   characteristic === await service.getCharacteristic('uuid2');
> >>   service === await device.gatt.getPrimaryService('uuid');
> >>   await device.gatt.getPrimaryService('uuid3');  // NotFoundError
> >>   device.gatt.disconnect();
> >>   // 'uuid' service removed, replaced with 'uuid3' service.
> >>   await device.gatt.connect();
> >
> > This seems to ignore that fact that the changes can happens while
> > connected where the following events would be exactly the same.
>
> This example happens to show the change occurring while disconnected,
> in order to highlight the difference from the as-if-non-bonded case.
> If the change happens while the device is connected and after the
> service has been retrieved during the current connection, I think the
> bonded and non-bonded options act the same. Have I missed something?
>
> >>   // 'servicechanged' fired some time after this. Let's say it doesn't
> >> arrive for a while.
> >>   service === await device.gatt.getPrimaryService('uuid');  // Cached.
> >>   characteristic === await service.getCharacteristic('uuid2');  //
> Cached.
> >>   let value = await characteristic.readValue(); // InvalidStateError?
> What
> >> GATT error does this cause?
> >>   await device.gatt.getPrimaryService('uuid3');  // Cached
> NotFoundError.
> >>   // Say 'servicechanged' arrives now. Listener logs it to console.
> >>   let service2 = await device.gatt.getPrimaryService('uuid3');  //
> Succeeds.
> >>   let service3 = await device.gatt.getPrimaryService('uuid'); //
> >> NotFoundError.
> >>
> >>
> >> Does that all make sense? Does it convince anyone to prefer
> as-if-bonded or
> >> as-if-not-bonded?
> >
> > The main concept difference appears to be persistent cache vs
> > temporary cache, the miss chance is slightly bigger on the former but
> > handling is almost the same either way.
>
> I don't really follow, sorry. IIUC, the persistent/as-if-bonded option
> guarantees sites don't miss a single notification sent right after the
> connection is established, and allows sites to write less code, but
> requires more code from the browser. The temporary/as-if-non-bonded
> option allows missed notifications, but allows a simpler browser
> implementation.
>
> > Btw, the persistent cache can
> > be used to check the services matches during the connection phase
> > which further reduces the chance of cache miss.
>
> I still think the persistent-but-non-bonded cache can fail to notice
> added and removed characteristics within an existing service whose
> range doesn't change. We don't need that to change in Bluez to
> implement Web Bluetooth, since we can just blame any resulting bugs on
> the user's platform, but I don't want to bake it into the web API.
>
> Jeffrey
>
> >> Jeffrey
> >>
> >>>
> >>> Rob
> >>>
> >>> Hi Rob,
> >>>
> >>> I really meant GATT notifications, even though advertise would
> >>> probably make more sense but Im not sure it is supported in a lot of
> >>> systems, certainly not Web Bluetooth. Anyway, I don't think suggesting
> >>> to use advertise will make the problem go away as devices may already
> >>> be in the market.
> >>>
> >>> Btw, the statement about having to register service changed events and
> >>> possibly holding stale services is true in any case regardless if we
> >>> persist the attributes or not because the device may change them while
> >>> connected not only when it is offline.
> >>>
> >>> On Thu, Mar 17, 2016 at 1:47 PM, Rob Moran <Rob.Moran@arm.com> wrote:
> >>> > Hi Luiz,
> >>> >
> >>> > I assume you are meaning devices such as eddystone beacons?
> >>> > I'm not sure if the Web Bluetooth requestDevice() function is the
> best
> >>> > interface to observe these sorts of beacons, but is more geared
> towards
> >>> > connecting and interacting with devices.
> >>> > For purely observing devices, I think another function alongside
> >>> > requestDevice() (observeDevices()?) may be a better approach which
> can
> >>> > maintain the cache required for these sorts of devices, is read-only
> and may
> >>> > not need the security restrictions of requestDevice().
> >>> >
> >>> > Specific scanning apps (such as the physical web app) may also be
> >>> > another option?
> >>> >
> >>> > ________________________________________
> >>> > From: Von Dentz, Luiz <luiz.von.dentz@intel.com>
> >>> > Sent: 17 March 2016 11:11
> >>> > To: Rob Moran
> >>> > Cc: Christiansen, Kenneth R; Jeffrey Yasskin; public-web-bluetooth
> >>> > Subject: Re: Should we expose all devices as if they were bonded?
> >>> >
> >>> > Hi Rob,
> >>> >
> >>> > There are device that advertise, notify one value and disconnect,
> >>> > which creates a race condition where the application/page may not be
> >>> > quick enough to catch the value which is then lost as the device
> >>> > disconnects immediately to save power.
> >>> >
> >>> > On Thu, Mar 17, 2016 at 1:06 PM, Rob Moran <Rob.Moran@arm.com>
> wrote:
> >>> >>
> >>> >> IMO having the device appear unbonded and requiring a user to
> >>> >> re-discover services and re-register for events, etc. after a
> disconnect is
> >>> >> a cleaner and more atomic approach.
> >>> >> Requiring the user to register for service changed events and
> possibly
> >>> >> holding stale services (as they may not exist after a reconnect)
> could
> >>> >> create more edge cases and potential errors to cover.
> >>> >>
> >>> >> In this scenario, I think the item to persist between connections is
> >>> >> the security context, so that any further reconnections don't
> require a user
> >>> >> action to undertake, but still honour the original service / name
> filters.
> >>> >>
> >>> >> Cheers,
> >>> >>
> >>> >> Rob
> >>> >> ________________________________________
> >>> >> From: Christiansen, Kenneth R <kenneth.r.christiansen@intel.com>
> >>> >> Sent: 17 March 2016 10:39
> >>> >> To: Jeffrey Yasskin; public-web-bluetooth
> >>> >> Subject: RE: Should we expose all devices as if they were bonded?
> >>> >>
> >>> >> At least for development purposes it would be nice to have them
> >>> >> unbounded (but I guess we could have a way to change the behavior in
> >>> >> devtools when it is open)
> >>> >>
> >>> >> I am not sure whether I want the notifications to be queued, at
> least
> >>> >> not by default. Think about something like temperature change and
> heart rate
> >>> >> measurements.
> >>> >>
> >>> >> Kenneth
> >>> >>
> >>> >>> -----Original Message-----
> >>> >>> From: Jeffrey Yasskin [mailto:jyasskin@google.com]
> >>> >>> Sent: Thursday, March 17, 2016 2:22 AM
> >>> >>> To: public-web-bluetooth <public-web-bluetooth@w3.org>
> >>> >>> Subject: Should we expose all devices as if they were bonded?
> >>> >>>
> >>> >>> Two issues came up recently where the Bluetooth spec defines
> different
> >>> >>> behavior depending on whether a device is bonded.
> >>> >>>
> >>> >>> In https://groups.google.com/a/chromium.org/d/topic/web-
> >>> >>> bluetooth/PQpZAFNlvT4/discussion
> >>> >>> and https://github.com/thegecko/web-bluetooth-dfu/issues/12, Luiz
> is
> >>> >>> suggesting that we have Web Bluetooth remember services,
> >>> >>> characteristics,
> >>> >>> and descriptors across disconnection, even when there's no physical
> >>> >>> bond.
> >>> >>> That's similar to treating the web site as bonded to the
> peripheral.
> >>> >>> We'd in
> >>> >>> the case of no bond, we'd re-discover the known services, etc.
> after
> >>> >>> re-
> >>> >>> connecting, and send service-changed events for the ones that have
> >>> >>> changed. We'd also allow users to hold onto Service, etc. objects
> >>> >>> across
> >>> >>> disconnect/connect pairs, and continue using the objects
> afterward. On
> >>> >>> the
> >>> >>> other hand, if we treat pages as un-bonded, users would need to
> >>> >>> re-fetch
> >>> >>> services, etc. before using them after a disconnect/reconnect pair.
> >>> >>>
> >>> >>> In https://github.com/WebBluetoothCG/web-bluetooth/issues/220 and
> >>> >>> https://bugs.chromium.org/p/chromium/issues/detail?id=589796, we
> have
> >>> >>> to decide whether users need to re-subscribe to notifications
> after a
> >>> >>> disconnection. If we treat pages as bonded, the notification state
> >>> >>> should
> >>> >>> persist across disconnections. If we treat pages as non-bonded, the
> >>> >>> state
> >>> >>> should reset to unsubscribed on disconnection. (3.G.3.3.3.3) If we
> >>> >>> keep the
> >>> >>> page subscribed across disconnection, users might expect us to
> queue
> >>> >>> notifications, or at least indications, and deliver them the next
> time
> >>> >>> the page
> >>> >>> is connected. Should we do the same if the page is unloaded? That
> kind
> >>> >>> of
> >>> >>> unbounded queueing seems problematic.
> >>> >>>
> >>> >>> And, of course, beyond always treating a page as bonded or
> not-bonded,
> >>> >>> we
> >>> >>> could make the page's bonded-ness depend on the presence of a
> physical
> >>> >>> bond.
> >>> >>>
> >>> >>> Are there other areas where treating the page as having or
> not-having
> >>> >>> a
> >>> >>> bond would cause divergent behavior?
> >>> >>>
> >>> >>> Which behavior do you folks think makes more sense for the web API?
> >>> >>>
> >>> >>> Jeffrey
> >>> >>
> >>> >> IMPORTANT NOTICE: The contents of this email and any attachments are
> >>> >> confidential and may also be privileged. If you are not the intended
> >>> >> recipient, please notify the sender immediately and do not disclose
> the
> >>> >> contents to any other person, use it for any purpose, or store or
> copy the
> >>> >> information in any medium. Thank you.
> >>> >>
> >>> >>
> >>> >
> >>> > IMPORTANT NOTICE: The contents of this email and any attachments are
> >>> > confidential and may also be privileged. If you are not the intended
> >>> > recipient, please notify the sender immediately and do not disclose
> the
> >>> > contents to any other person, use it for any purpose, or store or
> copy the
> >>> > information in any medium. Thank you.
> >>> >
> >>>
> >>> IMPORTANT NOTICE: The contents of this email and any attachments are
> >>> confidential and may also be privileged. If you are not the intended
> >>> recipient, please notify the sender immediately and do not disclose the
> >>> contents to any other person, use it for any purpose, or store or copy
> the
> >>> information in any medium. Thank you.
> >>>
> >>
>
>
Received on Thursday, 31 March 2016 14:48:37 UTC

This archive was generated by hypermail 2.4.0 : Friday, 17 January 2020 17:57:54 UTC