Coder Social home page Coder Social logo

web-bluetooth's Introduction

web-bluetooth

Bluetooth support for the Web.

This is a project of the W3C Web Bluetooth Community Group. We have a charter.

Specification

Try it out

Communication

web-bluetooth's People

Contributors

autokagami avatar beaufortfrancois avatar chengweih001 avatar chromakode avatar dati91 avatar dlech avatar dougt avatar foolip avatar g-ortuno avatar gabrielsanbrito avatar ijzerenhein avatar joelweinberger avatar jyasskin avatar marcoscaceres avatar mathiasbynens avatar mikehedman avatar miketaylr avatar motla avatar odejesush avatar reillyeon avatar saschanaz avatar scheib avatar sinz163 avatar stevennyman avatar thegecko avatar tkybpp avatar totati avatar yorkie avatar zakorgy avatar zcorpan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

web-bluetooth's Issues

`address` should be `instanceId`

MacOS doesn't provide the BT address for a peripheral, just a generated identifier.

This may also help avoid confusion between the public address, static address, private addresses, and IRK in picking a device's "address".

Define events more consistently with other web platform events

Most events in the web platform are specified along the lines of "Fire a trusted event with the name 'foo' at 'bar', using the Baz interface." Event names are almost always all-lowercase. The bluetooth events should be specified and named the same way, as opposed to being defined on their handler attributes.

We should also consider whether to make the various GATT objects participate in a tree so we could fire the events directly at the service or characteristic they relate to. There's some tension here with the desire to eventually expose these events to Service Workers, since a Service Worker that's just been woken up won't have GATT instances around to attach event handlers to. However, having navigator.bluetooth act as the root of any tree will at least make it possible to handle the events in a Service Worker.

Investigate how malicious devices could become trusted keyboards/mice

USB devices are trusted as keyboards and mice by default, which leads to well-known exploits like https://srlabs.de/badusb/.

How vulnerable are current operating systems to the same attacks over Bluetooth? For example, if I pair a device that looks like a fitbit, but which also exposes a HID keyboard service, will my OS trust the keyboard without warning me? If I pair a device, and it adds a keyboard service later, will my OS trust the new keyboard?

This is relevant to this project because we have to assume some devices will be vulnerable to GATT writes in ways that let the attacker compromise the firmware and add new services.

@jracle @armansito

BluetoothGATTCharacteristic.properties should expose a dictionary rather than an array or bitfield

Discussion on dev-webapi@mozilla indicates that it would probably be more webby to expose the set of Characteristic Properties as a dictionary of boolean values rather than the bitfield that raw Bluetooth exposes. This will also let us expose the Extended Properties descriptor (3.G.3.3.3.1) uniformly with the basic properties (3.G.3.3.1.1).

The Chrome Apps API exposes a list of strings, which splits the difference. I think it'll be easier for developers to use if we expose this as a dictionary (or Set?) rather than making them search a list.

Trying to expose the extended properties uniformly with the basic properties raises the question of whether properties should return a value or a Promise. The ATT message that discovers the Characteristic itself includes the basic properties, but if the Extended Properties bit is set there, the UA will need to discover a prefix of the Characteristic's Descriptors and read the value of the Characteristic Extended Properties, for at least 2 extra radio round-trips before the Characteristic can be returned. It's likely that developers won't inspect the properties field in most cases, since they're writing an application against a specific Service whose definition defines which characteristic properties are set, so I'm inclined to have properties return a Promise.

Should we limit supported Services to a whitelist?

Whitelisting a set of standardized Services would allow us to provide a better interface than the UUIDs-and-ArrayBuffers that most Bluetooth APIs require. It would also provide some nice security properties since we could hide the precise identity of the devices speaking these Services and could enforce that written values match the requirements set by the Service.

On the other hand, we want to let device vendors write web pages for their devices instead of making them resort to native apps, and lots of new devices, like plant health sensors, barcode scanners, lightbulbs, and dive meters aren't covered by the standard services.

Consider removing a few of getAll* methods

Currently BluetoothDevice define 3 variants of getAllServices:

Promise<BluetoothGATTServiceSequence> getAllServices ()
Promise<BluetoothGATTServiceSequence> getAllServices (BluetoothServiceUuid service)
Promise<BluetoothGATTServiceSequence> getAllServices (sequence<BluetoothServiceUuid> services)

I propose we keep only the first one, as most native APIs do.
Forcing browsers to implement the last 2 methods is overkill IMO.

In the same idea, I would also remove from BluetoothGATTService:

Promise<BluetoothGATTCharacteristicSequence> getAllCharacteristics (sequence<BluetoothCharacteristicUuid> characteristics);
Promise<BluetoothGATTServiceSequence>        getAllIncludedServices (sequence<BluetoothServiceUuid> services);

Finally, I'll remove from BluetoothGATTCharacteristic:

Promise<BluetoothGATTDescriptorSequence> getAllDescriptors (sequence<BluetoothDescriptorUuid> descriptors);

Design a way for developers to handle devices that come into range "later"

http://webbluetoothcg.github.io/web-bluetooth/use-cases.html#usecase_lazy_scale

  1. User opens a website that can communicate over Service A
  2. Website requests later access to devices talking Service A
  3. User approves request. (Check with Privacy if this step is needed.)
  4. Optional: User closes website.
  5. Device X begins advertising Service A.
  6. UA presents a list of websites that could handle Device X, allowing user to choose 0 or more.
  7. Chosen website is notified and begins interacting with Device X.

The notification could be an event handler in an open web page, or a mechanism like registerProtocolHandler that opens a new tab with a device ID embedded in the URL, or an event handler in a service worker. The event handlers could receive a BluetoothDevice instance, but the URL needs a stringified form, which the page could vivify using a to-be-defined function.

Minor fix to BluetoothGattCharacteristic.startNotifications description

The description should read "Once enabled, an application can listen to notifications /indications using the onCharacteristicValueChanged event." If the behavior will follow chrome.bluetoothLowEnergy, then this method (and the event) should enable (and propagate) handle-value indications as well.

Enforce a maximum length on writes

BT4.1 3.F.3.2.9 Long Attribute Values says:

The maximum length of an attribute value shall be 512 octets.

We should fail an attempt to write a value longer than that before sending it down to the OS or over the radio, in order to protect any fixed-length buffers hiding in those layers.

Can bluetooth objects be used after their originating document is closed?

If one document calls requestDevice() and gets a BluetoothDevice, and then passes that object to another document (through same-origin iframe or window.open?), does the object stay usable after the originating document is closed? After the originating frame is closed?

What do we need to write in the spec to pin that down?

Should the first version of the spec cover GATT over BR/EDR?

The wording right now is focused on the LE transport layer, but it might be possible to get the same security and privacy guarantees from GATT over BR/EDR. I'm inclined to focus on getting 1 transport layer right before adding a second, but would be happy to hear any more informed thoughts on the subject.

This came up in #14.

Should `requestDevice` automatically connect to the device?

Discovery and connection are separate steps in the Bluetooth spec and in most APIs that access Bluetooth. However, these APIs generally don't expose as compressed a discovery flow as this one, nor do they involve an "open-like" dialog where the user selects a device.

I don't know of a use for getting a handle to an un-connected device, but if you know of one please mention it here.

If there's a use, we need to expose that possibility. It's not clear whether we should expose it by having requestDevice() return an un-connected device regardless and making all developers call connect() explicitly, or by having requestDevice() default to returning a connected device, but with an option to override that default.

Remove Instance IDs

The instanceid attribute currently exists on BluetoothDevice, BluetoothGATTService, BluetoothGATTCharacteristic, and BluetoothGATTDescriptor. The instanceid can be used to

  1. Disambiguate multiple instances of objects with the same UUID.
  2. Get an object for the instance from the navigator.bluetooth.get* methods (BluetoothInteraction interface).

However, instance IDs may not be exposed on all platform APIs. E.G. See Apple's CBService.

Implementations of Web Bluetooth could manufacture IDs even when the OS API does not provide them to work around this. IDs would need to be invalidated whenever the association can't be maintained, e.g. device disconnection or on Service Change.

Further, the information does not seem essential to a minimum viable Web Bluetooth specification. Multiple service, characteristic, descriptor instances will be returned as unique objects, and applications can assign ID if necessary to them in the same way this specification wound need to on operating systems that do not expose an instance ID.

Remove BluetoothInteraction get* Methods

https://webbluetoothcg.github.io/web-bluetooth/#idl-def-BluetoothInteraction currently offers

    Promise<BluetoothGATTService>        getService (DOMString serviceInstanceId);
    Promise<BluetoothGATTCharacteristic> getCharacteristic (DOMString characteristicInstanceId);
    Promise<BluetoothGATTDescriptor>     getDescriptor (DOMString descriptorInstanceId);

I motion we remove these from the initial spec
a. To keep initial spec as simple as possible. Access to Service, Characteristic, and Descriptor objects is already exposed by the chain of objects, get*, and returned promises.
b. Scanning e.g. Android SDK, I don't see a way for the implementation to efficiently implement loading Service, Characteristic, and Descriptor objects from ID, the implementation would need to enumerate the full hierarchy anyway to search for matches.
c. InstanceIDs may not be easily accessible on all platforms, see #51 which proposes removing all instanceid attributes.

Security level of connections initiated by applications.

An interesting point that came up today involved connection security: should the API require all outgoing connections to be at a certain security level (encrypted, requiring authorization/authentication, etc)? Or should apps have the ability to specify the security level of the connection if they initiated it?

Specify we're returning Primary services in BluetoothDevice methods

Aside from removing 'All' from getAll* methods (#40) and removing a few of getAll* methods (#39), we could specify in the interface that we're returning only primary services.

Debating with myself, this would however not be in line with most native APIs, which solely specify getService(s).

This would give:
BluetoothDevice.getPrimaryService(s)

What service/characteristic/descriptor browsing interface should we define?

The chrome.bluetoothLowEnergy API makes developers asynchronously retrieve the full list of supported Services, then iterate over the list to find the UUID they want. Then they must repeat this for Included Services, Characteristics and Descriptors.

  1. Could we fully populate the Service/Characteristic/Descriptor tree on Device instantiation so that the accessors wouldn't need to be asynchronous?
  2. Should we expose a map from UUID to Service, etc. so developers wouldn't need to manually loop?
  3. Can this map completely replace the "list all Services", etc. methods, or are there going to be multiple instances with the same UUID path? (If all that happens is D > A > X and D > B > X, the map would still be sufficient for navigation, since paths of UUIDs would be unique.)

Specify how re-connection works

Currently connect() is missing auto-connect optional parameter. Do we have any concern to do this? Without auto-connect parameter, I think it will be hard to handle reconnection scenario. If a website already paired and connect with a Smart Device, Smart Device moves out-of-range. Is it nature to reconnect smart device if the user already trusted this website to connect with that specific device?

Figure out how much fingerprinting is needed/acceptable

The current Device interface exposes 2-3 unique IDs for the device (deviceID, address, and possibly name), and allows sites to enumerate the Services the device defines, which is probably also enough to fingerprint the device.

How much of this do we need to expose to let people write useful apps? Does the fact that a user has to explicitly pair each device with the site mitigate the privacy concern?

Reference to SDP in BluetoothScanFilter.

The documentation for BluetoothScanFilter says the following:

When determining the list of Service UUIDs a device supports, the UA must include Services advertised by the device, and may include Services previously discovered through the Bluetooth Service Discovery Protocol (SDP).

This should probably be clarified a bit. SDP is used for discovering services over BR/EDR and, while GATT over BR/EDR is possible, these are not limited to GATT services. This should really read something like "..., and may include GATT services previously discovered through the Attribute Protocol (ATT) and/or Service Discovery Protocol (SDP)"

How to re-discovery service explicitly?

Currently requestDevice() defines two behaviors--connect and discovery services, after that I assume it cached everything, and API doesn't provide discover service method. It doesn't give applications refresh service lists.
Suppose there is one Bluetooth Smart device with 3 sensors, when we connect with the device, only one sensor is being activated, so only one Thermometer Service shows up, and we only cache one service. I guess it's possible to activate other sensors and the device update service list again, in this case, the application may need to discovery service again.

Should we have onCharacteristicAdded/Removed and onDescriptorAdded/Removed event handlers?

In current draft, "characteristics and/or descriptors that get added or removed from the service" are covered in onServiceChanged event handler.
Have you considered to separate characteristics added/removed to onCharacteristicAdded/Removed, and so as descriptors? Which might make the name more clear?
Besides, if we use a ServiceEvent with a BluetoothGattService attribute for "Service Changed", is there a way to let application know that it was a characteristic or descriptor added/removed from the service in your approach?
Could you share why you chose to aggregate them in onServiceChanged?

By the way, there is a DescriptorEvent in your spec which is not actually used, what's that for?

BluetoothDevice.getAllServices

The overloaded variants of getAllServices that filter the result by UUID should probably accept an argument called uuids or uuid instead of services/service. It's not clear just by looking at the signature that these are meant to be UUIDs and not service IDs.

Should also add a note on the format of the UUID. I.e. if 16-bit, 32-bit, 128-bit, or all formats are accepted.

Define Bluetooth terminology more precisely

The spec should probably define the set of Bluetooth host operations used in each step, while right now it just says things like "support a service" and "enable notifications". For security and privacy related operations, we'll need to say something about the allowed packet sequences.

This is extra tricky because it needs to be implementable on top of several platform APIs that say little about what operations they cause.

Write an implementation tips document

I'm expecting to write the spec in terms of the Bluetooth operations that each javascript function needs to map to, but implementations are going to need to work in terms of platform features. It'll be helpful to have a document for implementers to follow that explains what platform (Win, MacOS, iOS, Linux (BlueZ?), Android) commands to use for each operation.

Allow browsers to let users pick devices that don't match the BluetoothScanFilter.

Per @marcoscaceres' argument in http://lists.w3.org/Archives/Public/public-web-bluetooth/2014Aug/0024.html, we should allow browsers to let users pick devices that don't match the filter the website requested. This is likely to cause the website to fail, but we shouldn't make allowing it non-conforming.

http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#attr-input-accept uses "User agents should prevent the user from selecting files that are not accepted by one (or more) of these tokens.", so that's probably good wording for this spec also.

Secondary services in BluetoothDevice.getAllServices?

GATT services can be primary and secondary and a usually service discovery procedure will involve two separate requests to obtain the handles of primary/secondary services (the attribute types for the service declaration attributes have different UUIDs for primary and secondary services). I guess the spec should say that the implementation should discover ALL GATT services?

Following on the above, should the getAllServices methods then return ALL services? The documentation currently says that they will only return primary services.

From what I've seen, there are almost NO BLE devices out in the field that have bothered with exposing secondary services (or even included services for that matter) so clients will probably be mostly interested in primary services. That said, maybe this API function should accept some sort of filter to limit the result to primary vs secondary services and return both types by default? What do you think?

Can we / do we need to restrict writes to match the format descriptors?

The Characteristic Aggregate Format and Characteristic Presentation Format Descriptors constrain the array buffers representing a characteristic's value. If we restrict writes to match those formats, we might be able to avoid some device exploits.

  1. Do enough devices expose these descriptors for writable characteristics that we could enforce the formats without preventing developers from using most devices?
  2. Can we accept the risk of malicious websites being able to write arbitrary arrays to devices?
  3. What about descriptor values? Except for the standardized ones, they don't have any format that the browser could discover.

Blacklisting various services, characteristics, and descriptors.

The reason for having the BluetoothGattCharacteristic.startNotifications|stopNotifications methods in the first place is to prevent apps from directly writing to the Client Characteristic Configuration (CCC below) descriptor (which is used to enable/disable notifications and indications from the characteristic). This raises the following two points:

  • BluetoothGattDescriptor.writeValue should NOT allow writing to the CCC descriptor directly to prevent one application from disabling notifications/indications while another application is interested in them. Either that or the (CCC) descriptor perhaps shouldn't ever be exposed.
  • It should be made clear to the implementation side that startNotifications and stopNotifications internally needs to keep a reference count of notification "sessions" of sort to manage the value of the CCC descriptor.

Included Services should be children of their Device

The Bluetooth tree I added in bc0b42b says that an Included Service's parent is the Service that includes it. However, I can't find anything in the BT standard that says a Service may only be included by 1 parent service, and the Windows API actually exposes a list of parents.

Let's not specify an ordering for the secondary services under a Device since they may be included by different services in different orders, and those inclusion orders are the only thing most implementations would have to go on. We'll need to specify "the first GATT included service" without relying on the tree order.

Consider Object.observe for service and nearby-device changes

@slightlyoff pointed out that we might be able to use Object.observe instead of events to track changes to various bits of Bluetooth metadata. For example, if we define BluetoothDevice.prototype.services as the cached array of discovered BluetoothGattServices, we could observe it for changes instead of needing to define the serviceadded, etc. events. We'd need to be clear that this is a cache like BluetoothGattCharacteristic.value (#37), rather than an up-front-discovered list of all the services.

Similarly, we could define a navigator.bluetooth.connectedDevices array to handle devices getting disconnected and reconnected (#31). That also handles the problem of a re-opened web page finding the devices it already has access to.

Should `requestDevice` allow choosing more than 1 device?

While reading device discovery and issue #2, came to my mind the issue where an app wants to communicate with more than 1 device. I'm not talking about connecting to a class of devices, but am thinking of a control panel (say mouse/keyboard configuration in my case) where user will configure devices which expose same vendor-defined service. User would have to select more than 1 device in a popup, which is fine.

Security: require devices to opt-in

Most existing Bluetooth devices don't expect untrusted websites to be interacting with them. The use cases document mentions that "a mechanism similar to the GPU Blacklist may be appropriate". However there is many orders of magnitude more variety in bluetooth devices than there is in GPUs, so it seems infeasible to blacklist vulnerable devices. Instead, it might be wise to require devices to opt in to being accessible via the web API.

On the other hand, native apps on all major OSes already get unrestricted access to bluetooth with barely any prompting. So maybe we're already doomed :-(

Map to remove listing units

I don't have a concrete proposal, but feel something "map-like" might do the trick. This would handle all the look ups. Something like:

[MapClass] interface BluetoothUnitMap{
void clear(); // clear only custom types, maybe?
boolean delete(BlueToothKey key); //as above?
void forEach(BTMapCallBack callback, optional any thisArg);
BlueToothUnit get(BlueToothKey key);
boolean has(BlueToothKey key);
BluetoothUnitMap set(BlueToothKey key, UUID128 value);
sequence<BlueToothKey> keys();
}

callback BTMapCallBack(UUID128 value, BlueToothKey key, BluetoothUnitMap object);

typedef DOMString UUID128; //force it to conform to canonical form in prose. 
typedef CustomBlueToothKey DOMString; 
typedef (StandardBlueToothKey or CustomBlueToothKey)  BlueToothKey; 

enum StandardBlueToothKey{
   "energy.kilogram_calorie",
   ...
}

Consider removing the `value` field from Characteristics and Descriptors

In discussion on dev-webapi@mozilla, @ehsan argued that

The apps can cache the value property themselves if they want to. These types of weird cache only properties don't have any prior art. In general, if something is as simple as this (by setting an expando property) to implement in the application code in JS, we should try to avoid adding it to the API.

We can also add the cache later if we find everyone using it.

Removing this field would mean that the notification/indication events need to include an ArrayBuffer in their fields, in addition to the Characteristic or Descriptor, but that's not terrible.

Pick a format for the spec

Right now it's in ReSpec with HTML sectioning.

  • ReSpec avoids the need to build the spec outside the browser. It has limited support for cross-spec autolinking (w3c/respec#332). It doesn't support modern WebIDL constructs like stringifier (w3c/respec#31). It generates weird sub-sections for members of dictionaries, and while there's an undocumented noLegacyStyle switch to turn them off, that simply deletes the associated documentation rather than just formatting it better (w3c/respec#334).
  • ReSpec also has an undocumented Markdown syntax (w3c/respec-docs#7), which might make the document slightly easier to read.
  • https://github.com/slightlyoff/web-spec-framework is Polymer-based so also has no build step, but doesn't really provide any help with spec formatting.
  • https://github.com/tabatkins/bikeshed requires a build step, but is actually maintained and has good source-code text shortcuts and cross-spec linking.

I'm not going to investigate this in the short run, but if a clear preference emerges here, we can switch.

Should sites be able to enumerate Services they didn't explicitly ask for?

Once a user has paired a site with a device, the current spec allows the site to completely enumerate the Services, Characteristics, and Descriptors defined by the device. We could instead require the site to explicitly list all the Services it expects to interact with, and then invent some UI (but what?) to warn the user what abilities the site will have. Should we?

Rename getAll* methods with get*

My feeling is that 'All' in getAll* methods is overkill.

I would then replace all of getAll* by get*, e.g.:

  • BluetoothDevice.getServices
  • BluetoothGATTService.getCharacteristics
  • BluetoothGATTService.getIncludedServices
  • BluetoothGATTCharacteristic.getDescriptors

This would also be aligned with most existing native APIs (e.g. Android)

Enable applications to view added/changed/removed services upon Service Changed

Section Responding to Service Changes details the dispatch of events serviceadded, servicechanged, serviceremoved when the Service Changed characteristic is notified.

Currently it is difficult for an application to understand the entire context of changes because sets of added/changed/removed services are sent separately.

Likely the best option is to dispatch a single serviceschanged event with all sets of added/changed/removed included in the event, similar to MutationRecord.

An alternative would be to add two additional events sent before and after the serviceadded, servicechanged, serviceremoved events are sent, allowing applications to cache the data and process it after it has all been presented.

onDescriptorValueChanged event not so necessary.

I realize that I added this event to chrome.bluetoothLowEnergy (mostly for convenience/consistency with onCharacteristicValueChanged) but there may not be much value to it, since BluetoothGattDescriptor.readValue achieves the same thing and there is no notification/indication mechanism for descriptor values. I'm actually thinking of removing it in a future Chrome release from the Chrome API.

Just something to think about.

Specify how to determine services are the same

Responding to Service Changes specificaly avoids specifying how to identify services that are the same after a Service Changed indications ([[!BLUETOOTH41]] 3.G.7.1).

If the same Service appears in both removedEntities and addedEntities, remove it from both, and add it to changedServices. Services with different UUIDs or Primary/Secondary status must not be considered "the same", but this specification says nothing else about determining identity

The challenge is that operating system level APIs may limit a user agent's ability to determine which services are the same based on UUIDs & attribute handle.

@jyasskin mentioned:

Raw Bluetooth would let us say that one Service is "the same" as another if they have the same UUID and attribute handle. The wrappers that give things instance IDs would let us say two Services are "the same" if they have the same instance ID. But Apple doesn't expose either, so there's no guaranteed way to match things up.

https://developer.apple.com/library/ios/documentation/CoreBluetooth/Reference/CBPeripheralDelegate_Protocol/index.html#//apple_ref/occ/intfm/CBPeripheralDelegate/peripheral:didModifyServices: does talk about "find out whether any of the invalidated services that you were using (and want to continue using) have been added back to a different location in the peripheral’s database.", but it doesn't say how to do that, and if they have a different location (attribute handle?), they're not really the same service anyway.

Perhaps the specification can make a best-effort suggestion, and possibly a standard fallback algorithm if attribute handles are not available.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.