Communiceren met Bluetooth-apparaten via JavaScript

Met de Web Bluetooth API kunnen websites communiceren met Bluetooth-apparaten.

François Beaufort
François Beaufort

Wat als ik je vertelde dat websites op een veilige en privacybeschermende manier kunnen communiceren met Bluetooth-apparaten in de buurt? Op deze manier kunnen hartslagmeters, zingende gloeilampen en zelfs schildpadden rechtstreeks communiceren met een website.

Tot nu toe was de mogelijkheid om te communiceren met Bluetooth-apparaten alleen mogelijk voor platformspecifieke apps. De Web Bluetooth API wil dit veranderen en brengt dit ook naar webbrowsers.

Voordat we beginnen

In dit document wordt ervan uitgegaan dat u enige basiskennis hebt van hoe Bluetooth Low Energy (BLE) en het Generieke Attribuutprofiel werken.

Hoewel de Web Bluetooth API-specificatie nog niet definitief is, zijn de spec-auteurs actief op zoek naar enthousiaste ontwikkelaars om deze API uit te proberen en feedback te geven over de specificaties en feedback over de implementatie .

Een subset van de Web Bluetooth API is beschikbaar in ChromeOS, Chrome voor Android 6.0, Mac (Chrome 56) en Windows 10 (Chrome 70). Dit betekent dat u Bluetooth Low Energy-apparaten in de buurt kunt opvragen en er verbinding mee kunt maken, Bluetooth-kenmerken kunt lezen / schrijven , GATT-meldingen kunt ontvangen , kunt weten wanneer de verbinding met een Bluetooth-apparaat wordt verbroken en zelfs Bluetooth-descriptors kunt lezen en schrijven . Zie de browsercompatibiliteitstabel van MDN voor meer informatie.

Voor Linux en eerdere versies van Windows schakelt u de vlag #experimental-web-platform-features in about://flags .

Beschikbaar voor herkomstproeven

Om zoveel mogelijk feedback te krijgen van ontwikkelaars die de Web Bluetooth API in het veld gebruiken, heeft Chrome deze functie eerder aan Chrome 53 toegevoegd als een origin-proefversie voor ChromeOS, Android en Mac.

De proef is in januari 2017 succesvol afgerond.

Beveiligingsvereisten

Om de afwegingen op het gebied van beveiliging te begrijpen, raad ik het Web Bluetooth Security Model- bericht aan van Jeffrey Yasskin, een software-ingenieur in het Chrome-team, die aan de Web Bluetooth API-specificatie werkt.

Alleen HTTPS

Omdat deze experimentele API een krachtige nieuwe functie is die aan internet is toegevoegd, wordt deze alleen beschikbaar gesteld om contexten te beveiligen . Dit betekent dat u moet bouwen met TLS in gedachten.

Gebruikersgebaar vereist

Als beveiligingsfunctie moet het ontdekken van Bluetooth-apparaten met navigator.bluetooth.requestDevice worden geactiveerd door een gebruikersgebaar, zoals een aanraking of een muisklik. We hebben het over het luisteren naar pointerup , click en touchend -gebeurtenissen.

button.addEventListener('pointerup', function(event) {
  // Call navigator.bluetooth.requestDevice
});

Verdiep je in de code

De Web Bluetooth API is sterk afhankelijk van JavaScript- beloften . Als je er niet bekend mee bent, bekijk dan deze geweldige Promises-tutorial . Nog een ding, () => {} zijn ECMAScript 2015 Arrow-functies .

Bluetooth-apparaten aanvragen

Met deze versie van de Web Bluetooth API-specificatie kunnen websites die in de centrale rol draaien, verbinding maken met externe GATT-servers via een BLE-verbinding. Het ondersteunt communicatie tussen apparaten die Bluetooth 4.0 of hoger implementeren.

Wanneer een website toegang vraagt ​​tot apparaten in de buurt met behulp van navigator.bluetooth.requestDevice , vraagt ​​de browser de gebruiker met een apparaatkiezer waar hij of zij een apparaat kan kiezen of het verzoek kan annuleren.

Gebruikersprompt Bluetooth-apparaat.

De functie navigator.bluetooth.requestDevice() gebruikt een verplicht object dat filters definieert. Deze filters worden gebruikt om alleen apparaten te retourneren die overeenkomen met sommige geadverteerde Bluetooth GATT-services en/of de apparaatnaam.

Dienstenfilter

Om bijvoorbeeld Bluetooth-apparaten aan te vragen die reclame maken voor de Bluetooth GATT Battery Service :

navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Als uw Bluetooth GATT-service echter niet op de lijst met gestandaardiseerde Bluetooth GATT-services staat, kunt u de volledige Bluetooth UUID of een korte 16- of 32-bits vorm opgeven.

navigator.bluetooth.requestDevice({
  filters: [{
    services: [0x1234, 0x12345678, '99999999-0000-1000-8000-00805f9b34fb']
  }]
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Naamfilter

U kunt ook Bluetooth-apparaten aanvragen op basis van de apparaatnaam waarvoor reclame wordt gemaakt met de name , of zelfs een voorvoegsel van deze naam met de namePrefix filtersleutel. Houd er rekening mee dat u in dit geval ook de optionalServices -sleutel moet definiëren om toegang te krijgen tot services die niet in een servicefilter zijn opgenomen. Als u dat niet doet, krijgt u later een foutmelding wanneer u probeert toegang te krijgen.

navigator.bluetooth.requestDevice({
  filters: [{
    name: 'Francois robot'
  }],
  optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Fabrikantgegevensfilter

Het is ook mogelijk om Bluetooth-apparaten aan te vragen op basis van de fabrikantspecifieke gegevens die worden geadverteerd met de sleutel manufacturerData . Deze sleutel is een array van objecten met een verplichte Bluetooth-bedrijfsidentificatiesleutel met de naam companyIdentifier . U kunt ook een gegevensvoorvoegsel opgeven waarmee fabrikantgegevens worden gefilterd van Bluetooth-apparaten die daarmee beginnen. Houd er rekening mee dat u ook de optionalServices -sleutel moet definiëren om toegang te krijgen tot services die niet in een servicefilter zijn opgenomen. Als u dat niet doet, krijgt u later een foutmelding wanneer u probeert toegang te krijgen.

// Filter Bluetooth devices from Google company with manufacturer data bytes
// that start with [0x01, 0x02].
navigator.bluetooth.requestDevice({
  filters: [{
    manufacturerData: [{
      companyIdentifier: 0x00e0,
      dataPrefix: new Uint8Array([0x01, 0x02])
    }]
  }],
  optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Een masker kan ook worden gebruikt met een gegevensvoorvoegsel om bepaalde patronen in de gegevens van de fabrikant te matchen. Bekijk de uitleg over Bluetooth-gegevensfilters voor meer informatie.

Uitsluitingsfilters

Met de optie exclusionFilters in navigator.bluetooth.requestDevice() kunt u bepaalde apparaten uitsluiten van de browserkiezer. Het kan worden gebruikt om apparaten uit te sluiten die aan een breder filter voldoen, maar niet worden ondersteund.

// Request access to a bluetooth device whose name starts with "Created by".
// The device named "Created by Francois" has been reported as unsupported.
navigator.bluetooth.requestDevice({
  filters: [{
    namePrefix: "Created by"
  }],
  exclusionFilters: [{
    name: "Created by Francois"
  }],
  optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Geen filters

Ten slotte kunt u in plaats van filters de sleutel acceptAllDevices gebruiken om alle Bluetooth-apparaten in de buurt weer te geven. U moet ook de optionalServices -sleutel definiëren om toegang te krijgen tot bepaalde services. Als u dat niet doet, krijgt u later een foutmelding wanneer u probeert toegang te krijgen.

navigator.bluetooth.requestDevice({
  acceptAllDevices: true,
  optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Maak verbinding met een Bluetooth-apparaat

Dus wat doe je nu je een BluetoothDevice hebt? Laten we verbinding maken met de Bluetooth-afstandsbediening GATT-server die de service en karakteristieke definities bevat.

navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => {
  // Human-readable name of the device.
  console.log(device.name);

  // Attempts to connect to remote GATT Server.
  return device.gatt.connect();
})
.then(server => { /* … */ })
.catch(error => { console.error(error); });

Lees een Bluetooth-kenmerk

Hier maken we verbinding met de GATT-server van het externe Bluetooth-apparaat. Nu willen we een primaire GATT-service krijgen en een kenmerk lezen dat bij deze service hoort. Laten we bijvoorbeeld proberen het huidige laadniveau van de batterij van het apparaat af te lezen.

In het volgende voorbeeld is battery_level de gestandaardiseerde karakteristiek voor het batterijniveau .

navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => device.gatt.connect())
.then(server => {
  // Getting Battery Service…
  return server.getPrimaryService('battery_service');
})
.then(service => {
  // Getting Battery Level Characteristic…
  return service.getCharacteristic('battery_level');
})
.then(characteristic => {
  // Reading Battery Level…
  return characteristic.readValue();
})
.then(value => {
  console.log(`Battery percentage is ${value.getUint8(0)}`);
})
.catch(error => { console.error(error); });

Als u een aangepast Bluetooth GATT-kenmerk gebruikt, kunt u de volledige Bluetooth-UUID of een korte 16- of 32-bits vorm aan service.getCharacteristic opgeven.

Houd er rekening mee dat u ook een characteristicvaluechanged gebeurtenislistener aan een kenmerk kunt toevoegen om het lezen van de waarde ervan af te handelen. Bekijk het voorbeeld van Read Characteristic Value Changed om te zien hoe u optioneel ook aankomende GATT-meldingen kunt afhandelen.


.then(characteristic => {
  // Set up event listener for when characteristic value changes.
  characteristic.addEventListener('characteristicvaluechanged',
                                  handleBatteryLevelChanged);
  // Reading Battery Level…
  return characteristic.readValue();
})
.catch(error => { console.error(error); });

function handleBatteryLevelChanged(event) {
  const batteryLevel = event.target.value.getUint8(0);
  console.log('Battery percentage is ' + batteryLevel);
}

Schrijf naar een Bluetooth-kenmerk

Schrijven naar een Bluetooth GATT-kenmerk is net zo eenvoudig als het lezen ervan. Laten we deze keer het hartslagcontrolepunt gebruiken om de waarde van het veld Verbruikte energie op een hartslagmeter opnieuw in te stellen op 0.

Ik beloof dat er hier geen magie is. Het wordt allemaal uitgelegd op de pagina Hartslagcontrolepuntkarakteristieken .

navigator.bluetooth.requestDevice({ filters: [{ services: ['heart_rate'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_control_point'))
.then(characteristic => {
  // Writing 1 is the signal to reset energy expended.
  const resetEnergyExpended = Uint8Array.of(1);
  return characteristic.writeValue(resetEnergyExpended);
})
.then(_ => {
  console.log('Energy expended has been reset.');
})
.catch(error => { console.error(error); });

Ontvang GATT-meldingen

Laten we nu eens kijken hoe u op de hoogte kunt worden gesteld wanneer de hartslagmetingskarakteristiek op het apparaat verandert:

navigator.bluetooth.requestDevice({ filters: [{ services: ['heart_rate'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_measurement'))
.then(characteristic => characteristic.startNotifications())
.then(characteristic => {
  characteristic.addEventListener('characteristicvaluechanged',
                                  handleCharacteristicValueChanged);
  console.log('Notifications have been started.');
})
.catch(error => { console.error(error); });

function handleCharacteristicValueChanged(event) {
  const value = event.target.value;
  console.log('Received ' + value);
  // TODO: Parse Heart Rate Measurement value.
  // See https://github.com/WebBluetoothCG/demos/blob/gh-pages/heart-rate-sensor/heartRateSensor.js
}

In het meldingenvoorbeeld ziet u hoe u meldingen kunt stoppen met stopNotifications() en hoe u de toegevoegde characteristicvaluechanged gebeurtenislistener op de juiste manier kunt verwijderen.

Verbinding met een Bluetooth-apparaat verbreken

Voor een betere gebruikerservaring kunt u luisteren naar gebeurtenissen waarbij de verbinding is verbroken en de gebruiker uitnodigen om opnieuw verbinding te maken:

navigator.bluetooth.requestDevice({ filters: [{ name: 'Francois robot' }] })
.then(device => {
  // Set up event listener for when device gets disconnected.
  device.addEventListener('gattserverdisconnected', onDisconnected);

  // Attempts to connect to remote GATT Server.
  return device.gatt.connect();
})
.then(server => { /* … */ })
.catch(error => { console.error(error); });

function onDisconnected(event) {
  const device = event.target;
  console.log(`Device ${device.name} is disconnected.`);
}

U kunt ook device.gatt.disconnect() aanroepen om uw webapp los te koppelen van het Bluetooth-apparaat. Hierdoor worden bestaande gattserverdisconnected gebeurtenislisteners geactiveerd. Houd er rekening mee dat de communicatie met het Bluetooth-apparaat NIET wordt gestopt als een andere app al met het Bluetooth-apparaat communiceert. Bekijk het voorbeeld van het ontkoppelen van het apparaat en het voorbeeld van het automatisch opnieuw verbinden om dieper te duiken.

Lezen en schrijven naar Bluetooth-descriptors

Bluetooth GATT-descriptors zijn attributen die een karakteristieke waarde beschrijven. U kunt ze op dezelfde manier lezen en schrijven als Bluetooth GATT-kenmerken.

Laten we bijvoorbeeld eens kijken hoe we de gebruikersbeschrijving van het meetinterval van de gezondheidsthermometer van het apparaat kunnen lezen.

In het onderstaande voorbeeld is health_thermometer de Health Thermometer-service , measurement_interval het meetintervalkenmerk en gatt.characteristic_user_description de karakteristieke gebruikersbeschrijving .

navigator.bluetooth.requestDevice({ filters: [{ services: ['health_thermometer'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('health_thermometer'))
.then(service => service.getCharacteristic('measurement_interval'))
.then(characteristic => characteristic.getDescriptor('gatt.characteristic_user_description'))
.then(descriptor => descriptor.readValue())
.then(value => {
  const decoder = new TextDecoder('utf-8');
  console.log(`User Description: ${decoder.decode(value)}`);
})
.catch(error => { console.error(error); });

Nu we de gebruikersbeschrijving van het meetinterval van de gezondheidsthermometer van het apparaat hebben gelezen, gaan we kijken hoe we deze kunnen bijwerken en een aangepaste waarde kunnen schrijven.

navigator.bluetooth.requestDevice({ filters: [{ services: ['health_thermometer'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('health_thermometer'))
.then(service => service.getCharacteristic('measurement_interval'))
.then(characteristic => characteristic.getDescriptor('gatt.characteristic_user_description'))
.then(descriptor => {
  const encoder = new TextEncoder('utf-8');
  const userDescription = encoder.encode('Defines the time between measurements.');
  return descriptor.writeValue(userDescription);
})
.catch(error => { console.error(error); });

Voorbeelden, demo's en codelabs

Alle onderstaande Web Bluetooth-voorbeelden zijn met succes getest. Om optimaal van deze voorbeelden te kunnen genieten, raad ik u aan de [BLE Peripheral Simulator Android App] te installeren, die een BLE-randapparaat simuleert met een batterijservice, een hartslagservice of een gezondheidsthermometerservice.

Beginner

  • Apparaatinfo - haal basisapparaatinformatie op van een BLE-apparaat.
  • Batterijniveau - haal batterij-informatie op van een BLE-apparaat dat batterij-informatie adverteert.
  • Energie resetten - reset de energie die wordt verbruikt door een BLE-apparaat dat hartslag adverteert.
  • Karakteristieke eigenschappen - toon alle eigenschappen van een specifiek kenmerk van een BLE-apparaat.
  • Meldingen - start en stop karakteristieke meldingen van een BLE-apparaat.
  • Apparaat loskoppelen - verbreek de verbinding en ontvang een melding wanneer een BLE-apparaat wordt verbroken nadat er verbinding mee is gemaakt.
  • Kenmerken verkrijgen - verkrijg alle kenmerken van een geadverteerde service van een BLE-apparaat.
  • Haal descriptors op - haal de descriptors van alle kenmerken van een geadverteerde service op van een BLE-apparaat.
  • Fabrikantgegevensfilter - haal basisapparaatinformatie op van een BLE-apparaat dat overeenkomt met de gegevens van de fabrikant.
  • Uitsluitingsfilters - haal basisapparaatinformatie op van een BLE-apparaat met basisuitsluitingsfilters.

Het combineren van meerdere operaties

Bekijk ook onze samengestelde Web Bluetooth-demo's en officiële Web Bluetooth Codelabs .

Bibliotheken

  • web-bluetooth-utils is een npm-module die enkele gemaksfuncties aan de API toevoegt.
  • Een Web Bluetooth API-shim is beschikbaar in noble , de meest populaire Node.js BLE centrale module. Hierdoor kunt u noble webpacken/browserifyen zonder dat u een WebSocket-server of andere plug-ins nodig hebt.
  • angular-web-bluetooth is een module voor Angular die al het standaardwerk wegneemt dat nodig is om de Web Bluetooth API te configureren.

Hulpmiddelen

  • Aan de slag met Web Bluetooth is een eenvoudige webapp die alle JavaScript-standaardcode genereert om interactie met een Bluetooth-apparaat te starten. Voer een apparaatnaam, een service en een kenmerk in, definieer de eigenschappen ervan en u bent klaar om te gaan.
  • Als u al een Bluetooth-ontwikkelaar bent, genereert de Web Bluetooth Developer Studio Plugin ook de Web Bluetooth JavaScript-code voor uw Bluetooth-apparaat.

Tips

Er is een Bluetooth Internals- pagina beschikbaar in Chrome op about://bluetooth-internals zodat u alles kunt bekijken over Bluetooth-apparaten in de buurt: status, services, kenmerken en beschrijvingen.

Schermafbeelding van de interne pagina voor het debuggen van Bluetooth in Chrome
Interne pagina in Chrome voor het debuggen van Bluetooth-apparaten.

Ik raad ook aan om de officiële pagina met Web Bluetooth-bugs te archiveren, omdat het debuggen van Bluetooth soms moeilijk kan zijn.

Wat is het volgende

Controleer eerst de implementatiestatus van de browser en het platform om te weten welke delen van de Web Bluetooth API momenteel worden geïmplementeerd.

Hoewel het nog steeds onvolledig is, is hier een voorproefje van wat u in de nabije toekomst kunt verwachten:

  • Het scannen naar BLE-advertenties in de buurt gebeurt met navigator.bluetooth.requestLEScan() .
  • Een nieuwe serviceadded -gebeurtenis zal nieuw ontdekte Bluetooth GATT-services volgen, terwijl serviceremoved gebeurtenis de verwijderde zal volgen. Er wordt een nieuwe servicechanged gebeurtenis geactiveerd wanneer een kenmerk en/of descriptor wordt toegevoegd aan of verwijderd uit een Bluetooth GATT-service.

Toon ondersteuning voor de API

Bent u van plan de Web Bluetooth API te gebruiken? Uw publieke steun helpt het Chrome-team prioriteiten te stellen voor functies en laat andere browserleveranciers zien hoe belangrijk het is om deze te ondersteunen.

Stuur een tweet naar @ChromiumDev met de hashtag #WebBluetooth en laat ons weten waar en hoe u deze gebruikt.

Bronnen

Dankbetuigingen

Met dank aan Kayce Basques voor het beoordelen van dit artikel. Heldenafbeelding van SparkFun Electronics uit Boulder, VS.

,

Met de Web Bluetooth API kunnen websites communiceren met Bluetooth-apparaten.

François Beaufort
François Beaufort

Wat als ik je zou vertellen dat websites op een veilige en privacybeschermende manier kunnen communiceren met Bluetooth-apparaten in de buurt? Op deze manier kunnen hartslagmeters, zingende gloeilampen en zelfs schildpadden rechtstreeks communiceren met een website.

Tot nu toe was de mogelijkheid om met Bluetooth-apparaten te communiceren alleen mogelijk voor platformspecifieke apps. De Web Bluetooth API wil dit veranderen en brengt dit ook naar webbrowsers.

Voordat we beginnen

In dit document wordt ervan uitgegaan dat u enige basiskennis heeft van hoe Bluetooth Low Energy (BLE) en het Generieke Attribuutprofiel werken.

Hoewel de Web Bluetooth API-specificatie nog niet definitief is, zijn de spec-auteurs actief op zoek naar enthousiaste ontwikkelaars om deze API uit te proberen en feedback te geven over de specificaties en feedback over de implementatie .

Een subset van de Web Bluetooth API is beschikbaar in ChromeOS, Chrome voor Android 6.0, Mac (Chrome 56) en Windows 10 (Chrome 70). Dit betekent dat u Bluetooth Low Energy-apparaten in de buurt kunt opvragen en er verbinding mee kunt maken, Bluetooth-kenmerken kunt lezen / schrijven , GATT-meldingen kunt ontvangen , kunt weten wanneer de verbinding met een Bluetooth-apparaat wordt verbroken en zelfs Bluetooth-descriptors kunt lezen en schrijven . Zie de browsercompatibiliteitstabel van MDN voor meer informatie.

Voor Linux en eerdere versies van Windows schakelt u de vlag #experimental-web-platform-features in about://flags .

Beschikbaar voor herkomstproeven

Om zoveel mogelijk feedback te krijgen van ontwikkelaars die de Web Bluetooth API in het veld gebruiken, heeft Chrome deze functie eerder aan Chrome 53 toegevoegd als een origin-proefversie voor ChromeOS, Android en Mac.

De proef is in januari 2017 succesvol afgerond.

Beveiligingsvereisten

Om de afwegingen op het gebied van beveiliging te begrijpen, raad ik het Web Bluetooth Security Model- bericht aan van Jeffrey Yasskin, een software-ingenieur in het Chrome-team, die aan de Web Bluetooth API-specificatie werkt.

Alleen HTTPS

Omdat deze experimentele API een krachtige nieuwe functie is die aan internet is toegevoegd, wordt deze alleen beschikbaar gesteld om contexten te beveiligen . Dit betekent dat u moet bouwen met TLS in gedachten.

Gebruikersgebaar vereist

Als beveiligingsfunctie moet het ontdekken van Bluetooth-apparaten met navigator.bluetooth.requestDevice worden geactiveerd door een gebruikersgebaar, zoals een aanraking of een muisklik. We hebben het over het luisteren naar pointerup , click en touchend -gebeurtenissen.

button.addEventListener('pointerup', function(event) {
  // Call navigator.bluetooth.requestDevice
});

Verdiep je in de code

De Web Bluetooth API is sterk afhankelijk van JavaScript- beloften . Als je er niet bekend mee bent, bekijk dan deze geweldige Promises-tutorial . Nog een ding, () => {} zijn ECMAScript 2015 Arrow-functies .

Bluetooth-apparaten aanvragen

Met deze versie van de Web Bluetooth API-specificatie kunnen websites die in de centrale rol draaien, verbinding maken met externe GATT-servers via een BLE-verbinding. Het ondersteunt communicatie tussen apparaten die Bluetooth 4.0 of hoger implementeren.

Wanneer een website toegang vraagt ​​tot apparaten in de buurt met behulp van navigator.bluetooth.requestDevice , vraagt ​​de browser de gebruiker met een apparaatkiezer waar hij een apparaat kan kiezen of het verzoek kan annuleren.

Gebruikersprompt Bluetooth-apparaat.

De functie navigator.bluetooth.requestDevice() gebruikt een verplicht object dat filters definieert. Deze filters worden gebruikt om alleen apparaten te retourneren die overeenkomen met sommige geadverteerde Bluetooth GATT-services en/of de apparaatnaam.

Dienstenfilter

Om bijvoorbeeld Bluetooth-apparaten aan te vragen die reclame maken voor de Bluetooth GATT Battery Service :

navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Als uw Bluetooth GATT-service echter niet op de lijst met gestandaardiseerde Bluetooth GATT-services staat, kunt u de volledige Bluetooth UUID of een korte 16- of 32-bits vorm opgeven.

navigator.bluetooth.requestDevice({
  filters: [{
    services: [0x1234, 0x12345678, '99999999-0000-1000-8000-00805f9b34fb']
  }]
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Naamfilter

U kunt ook Bluetooth-apparaten aanvragen op basis van de apparaatnaam waarvoor reclame wordt gemaakt met de name , of zelfs een voorvoegsel van deze naam met de namePrefix filtersleutel. Houd er rekening mee dat u in dit geval ook de optionalServices -sleutel moet definiëren om toegang te krijgen tot services die niet in een servicefilter zijn opgenomen. Als u dat niet doet, krijgt u later een foutmelding wanneer u probeert toegang te krijgen.

navigator.bluetooth.requestDevice({
  filters: [{
    name: 'Francois robot'
  }],
  optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Fabrikantgegevensfilter

Het is ook mogelijk om Bluetooth-apparaten aan te vragen op basis van de fabrikantspecifieke gegevens die worden geadverteerd met de manufacturerData -sleutel. Deze sleutel is een array van objecten met een verplichte Bluetooth-bedrijfsidentificatiesleutel met de naam companyIdentifier . U kunt ook een gegevensvoorvoegsel opgeven waarmee fabrikantgegevens worden gefilterd van Bluetooth-apparaten die daarmee beginnen. Houd er rekening mee dat u ook de optionalServices -sleutel moet definiëren om toegang te krijgen tot services die niet in een servicefilter zijn opgenomen. Als u dat niet doet, krijgt u later een foutmelding wanneer u probeert toegang te krijgen.

// Filter Bluetooth devices from Google company with manufacturer data bytes
// that start with [0x01, 0x02].
navigator.bluetooth.requestDevice({
  filters: [{
    manufacturerData: [{
      companyIdentifier: 0x00e0,
      dataPrefix: new Uint8Array([0x01, 0x02])
    }]
  }],
  optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Een masker kan ook worden gebruikt met een gegevensvoorvoegsel om bepaalde patronen in de gegevens van de fabrikant te matchen. Bekijk de uitleg over Bluetooth-gegevensfilters voor meer informatie.

Uitsluitingsfilters

Met de optie exclusionFilters in navigator.bluetooth.requestDevice() kunt u bepaalde apparaten uitsluiten van de browserkiezer. Het kan worden gebruikt om apparaten uit te sluiten die overeenkomen met een breder filter, maar niet worden ondersteund.

// Request access to a bluetooth device whose name starts with "Created by".
// The device named "Created by Francois" has been reported as unsupported.
navigator.bluetooth.requestDevice({
  filters: [{
    namePrefix: "Created by"
  }],
  exclusionFilters: [{
    name: "Created by Francois"
  }],
  optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Geen filters

Ten slotte kunt u in plaats van filters de sleutel acceptAllDevices gebruiken om alle Bluetooth-apparaten in de buurt weer te geven. U moet ook de optionalServices -sleutel definiëren om toegang te krijgen tot bepaalde services. Als u dat niet doet, krijgt u later een foutmelding wanneer u probeert toegang te krijgen.

navigator.bluetooth.requestDevice({
  acceptAllDevices: true,
  optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Maak verbinding met een Bluetooth-apparaat

Dus wat doe je nu je een BluetoothDevice hebt? Laten we verbinding maken met de Bluetooth-afstandsbediening GATT-server die de service en karakteristieke definities bevat.

navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => {
  // Human-readable name of the device.
  console.log(device.name);

  // Attempts to connect to remote GATT Server.
  return device.gatt.connect();
})
.then(server => { /* … */ })
.catch(error => { console.error(error); });

Lees een Bluetooth-kenmerk

Hier maken we verbinding met de GATT-server van het externe Bluetooth-apparaat. Nu willen we een primaire GATT-service krijgen en een kenmerk lezen dat bij deze service hoort. Laten we bijvoorbeeld proberen het huidige laadniveau van de batterij van het apparaat af te lezen.

In het volgende voorbeeld is battery_level de gestandaardiseerde karakteristiek voor het batterijniveau .

navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => device.gatt.connect())
.then(server => {
  // Getting Battery Service…
  return server.getPrimaryService('battery_service');
})
.then(service => {
  // Getting Battery Level Characteristic…
  return service.getCharacteristic('battery_level');
})
.then(characteristic => {
  // Reading Battery Level…
  return characteristic.readValue();
})
.then(value => {
  console.log(`Battery percentage is ${value.getUint8(0)}`);
})
.catch(error => { console.error(error); });

Als u een aangepast Bluetooth GATT-kenmerk gebruikt, kunt u de volledige Bluetooth-UUID of een korte 16- of 32-bits vorm aan service.getCharacteristic opgeven.

Houd er rekening mee dat u ook een characteristicvaluechanged gebeurtenislistener aan een kenmerk kunt toevoegen om het lezen van de waarde ervan af te handelen. Bekijk het voorbeeld van Read Characteristic Value Changed om te zien hoe u optioneel ook aankomende GATT-meldingen kunt afhandelen.


.then(characteristic => {
  // Set up event listener for when characteristic value changes.
  characteristic.addEventListener('characteristicvaluechanged',
                                  handleBatteryLevelChanged);
  // Reading Battery Level…
  return characteristic.readValue();
})
.catch(error => { console.error(error); });

function handleBatteryLevelChanged(event) {
  const batteryLevel = event.target.value.getUint8(0);
  console.log('Battery percentage is ' + batteryLevel);
}

Schrijf naar een Bluetooth-kenmerk

Schrijven naar een Bluetooth GATT-kenmerk is net zo eenvoudig als lezen. Laten we deze keer het hartslagcontrolepunt gebruiken om de waarde van het veld Verbruikte energie op een hartslagmeter opnieuw in te stellen op 0.

Ik beloof dat er hier geen magie is. Het wordt allemaal uitgelegd op de pagina Hartslagcontrolepuntkarakteristieken .

navigator.bluetooth.requestDevice({ filters: [{ services: ['heart_rate'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_control_point'))
.then(characteristic => {
  // Writing 1 is the signal to reset energy expended.
  const resetEnergyExpended = Uint8Array.of(1);
  return characteristic.writeValue(resetEnergyExpended);
})
.then(_ => {
  console.log('Energy expended has been reset.');
})
.catch(error => { console.error(error); });

Ontvang GATT-meldingen

Laten we nu eens kijken hoe u op de hoogte kunt worden gesteld wanneer de hartslagmetingskarakteristiek op het apparaat verandert:

navigator.bluetooth.requestDevice({ filters: [{ services: ['heart_rate'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_measurement'))
.then(characteristic => characteristic.startNotifications())
.then(characteristic => {
  characteristic.addEventListener('characteristicvaluechanged',
                                  handleCharacteristicValueChanged);
  console.log('Notifications have been started.');
})
.catch(error => { console.error(error); });

function handleCharacteristicValueChanged(event) {
  const value = event.target.value;
  console.log('Received ' + value);
  // TODO: Parse Heart Rate Measurement value.
  // See https://github.com/WebBluetoothCG/demos/blob/gh-pages/heart-rate-sensor/heartRateSensor.js
}

In het voorbeeld van Meldingen ziet u hoe u meldingen kunt stoppen met stopNotifications() en hoe u de toegevoegde characteristicvaluechanged gebeurtenislistener op de juiste manier kunt verwijderen.

Verbinding met een Bluetooth-apparaat verbreken

Voor een betere gebruikerservaring kunt u luisteren naar gebeurtenissen waarbij de verbinding is verbroken en de gebruiker uitnodigen om opnieuw verbinding te maken:

navigator.bluetooth.requestDevice({ filters: [{ name: 'Francois robot' }] })
.then(device => {
  // Set up event listener for when device gets disconnected.
  device.addEventListener('gattserverdisconnected', onDisconnected);

  // Attempts to connect to remote GATT Server.
  return device.gatt.connect();
})
.then(server => { /* … */ })
.catch(error => { console.error(error); });

function onDisconnected(event) {
  const device = event.target;
  console.log(`Device ${device.name} is disconnected.`);
}

U kunt ook device.gatt.disconnect() aanroepen om uw webapp los te koppelen van het Bluetooth-apparaat. Hierdoor worden bestaande gattserverdisconnected gebeurtenislisteners geactiveerd. Houd er rekening mee dat de communicatie met het Bluetooth-apparaat NIET wordt gestopt als een andere app al met het Bluetooth-apparaat communiceert. Bekijk het voorbeeld van het ontkoppelen van het apparaat en het voorbeeld van het automatisch opnieuw verbinden om dieper te duiken.

Lezen en schrijven naar Bluetooth-descriptors

Bluetooth GATT-descriptors zijn attributen die een karakteristieke waarde beschrijven. U kunt ze op dezelfde manier lezen en schrijven als Bluetooth GATT-kenmerken.

Laten we bijvoorbeeld eens kijken hoe we de gebruikersbeschrijving van het meetinterval van de gezondheidsthermometer van het apparaat kunnen lezen.

In het onderstaande voorbeeld is health_thermometer de Health Thermometer-service , measurement_interval het meetintervalkenmerk en gatt.characteristic_user_description de karakteristieke gebruikersbeschrijving .

navigator.bluetooth.requestDevice({ filters: [{ services: ['health_thermometer'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('health_thermometer'))
.then(service => service.getCharacteristic('measurement_interval'))
.then(characteristic => characteristic.getDescriptor('gatt.characteristic_user_description'))
.then(descriptor => descriptor.readValue())
.then(value => {
  const decoder = new TextDecoder('utf-8');
  console.log(`User Description: ${decoder.decode(value)}`);
})
.catch(error => { console.error(error); });

Nu we de gebruikersbeschrijving van het meetinterval van de gezondheidsthermometer van het apparaat hebben gelezen, gaan we kijken hoe we deze kunnen bijwerken en een aangepaste waarde kunnen schrijven.

navigator.bluetooth.requestDevice({ filters: [{ services: ['health_thermometer'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('health_thermometer'))
.then(service => service.getCharacteristic('measurement_interval'))
.then(characteristic => characteristic.getDescriptor('gatt.characteristic_user_description'))
.then(descriptor => {
  const encoder = new TextEncoder('utf-8');
  const userDescription = encoder.encode('Defines the time between measurements.');
  return descriptor.writeValue(userDescription);
})
.catch(error => { console.error(error); });

Voorbeelden, demo's en codelabs

Alle onderstaande Web Bluetooth-voorbeelden zijn met succes getest. Om optimaal van deze voorbeelden te kunnen genieten, raad ik u aan de [BLE Peripheral Simulator Android App] te installeren, die een BLE-randapparaat simuleert met een batterijservice, een hartslagservice of een gezondheidsthermometerservice.

Beginner

  • Apparaatinfo - haal basisapparaatinformatie op van een BLE-apparaat.
  • Batterijniveau - haal batterij-informatie op van een BLE-apparaat dat batterij-informatie adverteert.
  • Energie resetten - reset de energie die wordt verbruikt door een BLE-apparaat dat hartslag adverteert.
  • Karakteristieke eigenschappen - toon alle eigenschappen van een specifiek kenmerk van een BLE-apparaat.
  • Meldingen - start en stop karakteristieke meldingen van een BLE-apparaat.
  • Apparaat loskoppelen - verbreek de verbinding en ontvang een melding wanneer een BLE-apparaat wordt verbroken nadat er verbinding mee is gemaakt.
  • Kenmerken verkrijgen - verkrijg alle kenmerken van een geadverteerde service van een BLE-apparaat.
  • Haal descriptors op - haal de descriptors van alle kenmerken van een geadverteerde service op van een BLE-apparaat.
  • Fabrikantgegevensfilter - haal basisapparaatinformatie op van een BLE-apparaat dat overeenkomt met de gegevens van de fabrikant.
  • Uitsluitingsfilters - haal basisapparaatinformatie op van een BLE-apparaat met basisuitsluitingsfilters.

Meerdere bewerkingen combineren

Bekijk ook onze samengestelde Web Bluetooth-demo's en officiële Web Bluetooth Codelabs .

Bibliotheken

  • web-bluetooth-utils is een npm-module die enkele gemaksfuncties aan de API toevoegt.
  • Een Web Bluetooth API-shim is beschikbaar in noble , de meest populaire Node.js BLE centrale module. Hierdoor kunt u noble webpacken/browserifyen zonder dat u een WebSocket-server of andere plug-ins nodig hebt.
  • angular-web-bluetooth is een module voor Angular die al het standaardwerk wegneemt dat nodig is om de Web Bluetooth API te configureren.

Hulpmiddelen

  • Aan de slag met Web Bluetooth is een eenvoudige webapp die alle JavaScript-standaardcode genereert om interactie met een Bluetooth-apparaat te starten. Voer een apparaatnaam, een service en een kenmerk in, definieer de eigenschappen ervan en u bent klaar om te gaan.
  • Als u al een Bluetooth-ontwikkelaar bent, genereert de Web Bluetooth Developer Studio Plugin ook de Web Bluetooth JavaScript-code voor uw Bluetooth-apparaat.

Tips

Er is een Bluetooth Internals- pagina beschikbaar in Chrome op about://bluetooth-internals zodat u alles kunt bekijken over Bluetooth-apparaten in de buurt: status, services, kenmerken en beschrijvingen.

Schermafbeelding van de interne pagina voor het debuggen van Bluetooth in Chrome
Interne pagina in Chrome voor het debuggen van Bluetooth-apparaten.

Ik raad ook aan om de officiële pagina met Web Bluetooth-bugs op te slaan, omdat het debuggen van Bluetooth soms moeilijk kan zijn.

Wat is het volgende

Controleer eerst de implementatiestatus van de browser en het platform om te weten welke delen van de Web Bluetooth API momenteel worden geïmplementeerd.

Hoewel het nog steeds onvolledig is, is hier een voorproefje van wat u in de nabije toekomst kunt verwachten:

  • Het scannen naar BLE-advertenties in de buurt gebeurt met navigator.bluetooth.requestLEScan() .
  • Een nieuwe serviceadded -gebeurtenis zal nieuw ontdekte Bluetooth GATT-services volgen, terwijl serviceremoved gebeurtenis de verwijderde zal volgen. Er wordt een nieuwe servicechanged gebeurtenis geactiveerd wanneer een kenmerk en/of descriptor wordt toegevoegd aan of verwijderd uit een Bluetooth GATT-service.

Toon ondersteuning voor de API

Bent u van plan de Web Bluetooth API te gebruiken? Uw publieke steun helpt het Chrome-team prioriteiten te stellen voor functies en laat andere browserleveranciers zien hoe belangrijk het is om deze te ondersteunen.

Stuur een tweet naar @ChromiumDev met de hashtag #WebBluetooth en laat ons weten waar en hoe u deze gebruikt.

Bronnen

Dankbetuigingen

Met dank aan Kayce Basques voor het beoordelen van dit artikel. Heldenafbeelding van SparkFun Electronics uit Boulder, VS.

,

Met de Web Bluetooth API kunnen websites communiceren met Bluetooth-apparaten.

François Beaufort
François Beaufort

Wat als ik je zou vertellen dat websites op een veilige en privacybeschermende manier kunnen communiceren met Bluetooth-apparaten in de buurt? Op deze manier kunnen hartslagmeters, zingende gloeilampen en zelfs schildpadden rechtstreeks communiceren met een website.

Tot nu toe was de mogelijkheid om met Bluetooth-apparaten te communiceren alleen mogelijk voor platformspecifieke apps. De Web Bluetooth API wil dit veranderen en brengt dit ook naar webbrowsers.

Voordat we beginnen

In dit document wordt ervan uitgegaan dat u enige basiskennis hebt van hoe Bluetooth Low Energy (BLE) en het Generieke Attribuutprofiel werken.

Hoewel de Web Bluetooth API-specificatie nog niet definitief is, zijn de spec-auteurs actief op zoek naar enthousiaste ontwikkelaars om deze API uit te proberen en feedback te geven over de specificaties en feedback over de implementatie .

Een subset van de Web Bluetooth API is beschikbaar in ChromeOS, Chrome voor Android 6.0, Mac (Chrome 56) en Windows 10 (Chrome 70). Dit betekent dat u Bluetooth Low Energy-apparaten in de buurt kunt opvragen en er verbinding mee kunt maken, Bluetooth-kenmerken kunt lezen / schrijven , GATT-meldingen kunt ontvangen , kunt weten wanneer de verbinding met een Bluetooth-apparaat wordt verbroken en zelfs Bluetooth-descriptors kunt lezen en schrijven . Zie de browsercompatibiliteitstabel van MDN voor meer informatie.

Voor Linux en eerdere versies van Windows schakelt u de vlag #experimental-web-platform-features in about://flags .

Beschikbaar voor herkomstproeven

Om zoveel mogelijk feedback te krijgen van ontwikkelaars die de Web Bluetooth API in het veld gebruiken, heeft Chrome deze functie eerder aan Chrome 53 toegevoegd als een origin-proefversie voor ChromeOS, Android en Mac.

De proef is in januari 2017 succesvol afgerond.

Beveiligingsvereisten

Om de afwegingen op het gebied van beveiliging te begrijpen, raad ik het Web Bluetooth Security Model- bericht aan van Jeffrey Yasskin, een software-ingenieur in het Chrome-team, die aan de Web Bluetooth API-specificatie werkt.

Alleen HTTPS

Omdat deze experimentele API een krachtige nieuwe functie is die aan internet is toegevoegd, wordt deze alleen beschikbaar gesteld om contexten te beveiligen . Dit betekent dat u moet bouwen met TLS in gedachten.

Gebruikersgebaar vereist

Als beveiligingsfunctie moet het ontdekken van Bluetooth-apparaten met navigator.bluetooth.requestDevice worden geactiveerd door een gebruikersgebaar, zoals een aanraking of een muisklik. We hebben het over het luisteren naar pointerup , click en touchend -gebeurtenissen.

button.addEventListener('pointerup', function(event) {
  // Call navigator.bluetooth.requestDevice
});

Verdiep je in de code

De Web Bluetooth API is sterk afhankelijk van JavaScript- beloften . Als je er niet bekend mee bent, bekijk dan deze geweldige Promises-tutorial . Nog een ding, () => {} zijn ECMAScript 2015 Arrow-functies .

Bluetooth-apparaten aanvragen

Met deze versie van de Web Bluetooth API-specificatie kunnen websites die in de centrale rol draaien, verbinding maken met externe GATT-servers via een BLE-verbinding. Het ondersteunt communicatie tussen apparaten die Bluetooth 4.0 of hoger implementeren.

Wanneer een website toegang vraagt ​​tot apparaten in de buurt met behulp van navigator.bluetooth.requestDevice , vraagt ​​de browser de gebruiker met een apparaatkiezer waar hij of zij een apparaat kan kiezen of het verzoek kan annuleren.

Gebruikersprompt Bluetooth-apparaat.

De functie navigator.bluetooth.requestDevice() gebruikt een verplicht object dat filters definieert. Deze filters worden gebruikt om alleen apparaten te retourneren die overeenkomen met sommige geadverteerde Bluetooth GATT-services en/of de apparaatnaam.

Dienstenfilter

Om bijvoorbeeld Bluetooth-apparaten aan te vragen die reclame maken voor de Bluetooth GATT Battery Service :

navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Als uw Bluetooth GATT-service echter niet op de lijst met gestandaardiseerde Bluetooth GATT-services staat, kunt u de volledige Bluetooth UUID of een korte 16- of 32-bits vorm opgeven.

navigator.bluetooth.requestDevice({
  filters: [{
    services: [0x1234, 0x12345678, '99999999-0000-1000-8000-00805f9b34fb']
  }]
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Naamfilter

U kunt ook Bluetooth -apparaten aanvragen op basis van de apparaatnaam die wordt geadverteerd met de name Filters -toets, of zelfs een voorvoegsel van deze naam met de naam van de namePrefix Filters. Merk op dat u in dit geval ook de toets optionalServices moet definiëren om toegang te krijgen tot services die niet in een servicefilter zijn opgenomen. Als u dat niet doet, krijgt u later een fout wanneer u ze probeert te openen.

navigator.bluetooth.requestDevice({
  filters: [{
    name: 'Francois robot'
  }],
  optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Gegevensfilter van de fabrikant

Het is ook mogelijk om Bluetooth -apparaten aan te vragen op basis van de fabrikant die specifieke gegevens worden geadverteerd met de sleutel van de manufacturerData filters. Deze sleutel is een reeks objecten met een verplichte Bluetooth -bedrijf ID -sleutel genaamd companyIdentifier . U kunt ook een gegevensvoorvoegsel verstrekken dat de gegevens van de fabrikant van Bluetooth -apparaten filtert die ermee beginnen. Houd er rekening mee dat u ook de toets optionalServices moet definiëren om toegang te krijgen tot services die niet in een servicefilter zijn opgenomen. Als u dat niet doet, krijgt u later een fout wanneer u ze probeert te openen.

// Filter Bluetooth devices from Google company with manufacturer data bytes
// that start with [0x01, 0x02].
navigator.bluetooth.requestDevice({
  filters: [{
    manufacturerData: [{
      companyIdentifier: 0x00e0,
      dataPrefix: new Uint8Array([0x01, 0x02])
    }]
  }],
  optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Een masker kan ook worden gebruikt met een gegevensvoorvoegsel om enkele patronen in de fabrikantgegevens te matchen. Bekijk de Bluetooth -datafilters uitleggen voor meer informatie.

Uitsluitingsfilters

Met de optie exclusionFilters in navigator.bluetooth.requestDevice() kunt u enkele apparaten uitsluiten van de browserplukker. Het kan worden gebruikt om apparaten uit te sluiten die overeenkomen met een breder filter maar niet worden ondersteund.

// Request access to a bluetooth device whose name starts with "Created by".
// The device named "Created by Francois" has been reported as unsupported.
navigator.bluetooth.requestDevice({
  filters: [{
    namePrefix: "Created by"
  }],
  exclusionFilters: [{
    name: "Created by Francois"
  }],
  optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Geen filters

Ten slotte kunt u in plaats van filters de sleutel acceptAllDevices gebruiken om alle nabijgelegen Bluetooth -apparaten weer te geven. U moet ook de toets optionalServices definiëren om toegang te krijgen tot sommige services. Als u dat niet doet, krijgt u later een fout wanneer u ze probeert te openen.

navigator.bluetooth.requestDevice({
  acceptAllDevices: true,
  optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });

Maak verbinding met een Bluetooth -apparaat

Dus wat doe je nu je een BluetoothDevice hebt? Laten we verbinding maken met de Bluetooth Remote Gatt Server die de service- en karakteristieke definities bevat.

navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => {
  // Human-readable name of the device.
  console.log(device.name);

  // Attempts to connect to remote GATT Server.
  return device.gatt.connect();
})
.then(server => { /* … */ })
.catch(error => { console.error(error); });

Lees een Bluetooth -kenmerk

Hier maken we verbinding met de GATT -server van het externe Bluetooth -apparaat. Nu willen we een primaire GATT -service krijgen en een kenmerk lezen dat bij deze service hoort. Laten we bijvoorbeeld proberen het huidige laadniveau van de batterij van het apparaat te lezen.

In het voorbeeld is battery_level het gestandaardiseerde kenmerk van het batterijniveau .

navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => device.gatt.connect())
.then(server => {
  // Getting Battery Service…
  return server.getPrimaryService('battery_service');
})
.then(service => {
  // Getting Battery Level Characteristic…
  return service.getCharacteristic('battery_level');
})
.then(characteristic => {
  // Reading Battery Level…
  return characteristic.readValue();
})
.then(value => {
  console.log(`Battery percentage is ${value.getUint8(0)}`);
})
.catch(error => { console.error(error); });

Als u een aangepaste Bluetooth GATT-kenmerk gebruikt, kunt u de volledige Bluetooth UUID of een korte 16- of 32-bit formulier voor service.getCharacteristic bieden. Getcharacteristisch.

Merk op dat je ook een characteristicvaluechanged -luisteraar kunt toevoegen op een kenmerk om het lezen van de waarde ervan af te handelen. Bekijk de voorbeeldwaarde van het lezen van de karakteristieke waarde om te zien hoe u ook optioneel aankomende GATT -meldingen kunt omgaan.


.then(characteristic => {
  // Set up event listener for when characteristic value changes.
  characteristic.addEventListener('characteristicvaluechanged',
                                  handleBatteryLevelChanged);
  // Reading Battery Level…
  return characteristic.readValue();
})
.catch(error => { console.error(error); });

function handleBatteryLevelChanged(event) {
  const batteryLevel = event.target.value.getUint8(0);
  console.log('Battery percentage is ' + batteryLevel);
}

Schrijf naar een Bluetooth -kenmerk

Schrijven op een Bluetooth Gatt -kenmerk is net zo eenvoudig als het lezen. Laten we deze keer het hartslagcontrolepunt gebruiken om de waarde van het energiegebruikte veld te resetten naar 0 op een hartslagmonitorapparaat.

Ik beloof dat er hier geen magie is. Het wordt allemaal uitgelegd op de karakteristieke pagina van de hartslagcontrole .

navigator.bluetooth.requestDevice({ filters: [{ services: ['heart_rate'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_control_point'))
.then(characteristic => {
  // Writing 1 is the signal to reset energy expended.
  const resetEnergyExpended = Uint8Array.of(1);
  return characteristic.writeValue(resetEnergyExpended);
})
.then(_ => {
  console.log('Energy expended has been reset.');
})
.catch(error => { console.error(error); });

Ontvang GATT -meldingen

Laten we nu eens kijken hoe u op de hoogte kunt worden gesteld wanneer het kenmerk van de hartslagmetingen op het apparaat verandert:

navigator.bluetooth.requestDevice({ filters: [{ services: ['heart_rate'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_measurement'))
.then(characteristic => characteristic.startNotifications())
.then(characteristic => {
  characteristic.addEventListener('characteristicvaluechanged',
                                  handleCharacteristicValueChanged);
  console.log('Notifications have been started.');
})
.catch(error => { console.error(error); });

function handleCharacteristicValueChanged(event) {
  const value = event.target.value;
  console.log('Received ' + value);
  // TODO: Parse Heart Rate Measurement value.
  // See https://github.com/WebBluetoothCG/demos/blob/gh-pages/heart-rate-sensor/heartRateSensor.js
}

Het monster van de meldingen laat zien hoe u meldingen kunt stoppen met stopNotifications() en verwijder de toegevoegde characteristicvaluechanged -luisteraar.

Ontkoppeling van een Bluetooth -apparaat

Om een ​​betere gebruikerservaring te bieden, wilt u misschien luisteren naar ontkoppingsgebeurtenissen en de gebruiker uitnodigen om opnieuw verbinding te maken:

navigator.bluetooth.requestDevice({ filters: [{ name: 'Francois robot' }] })
.then(device => {
  // Set up event listener for when device gets disconnected.
  device.addEventListener('gattserverdisconnected', onDisconnected);

  // Attempts to connect to remote GATT Server.
  return device.gatt.connect();
})
.then(server => { /* … */ })
.catch(error => { console.error(error); });

function onDisconnected(event) {
  const device = event.target;
  console.log(`Device ${device.name} is disconnected.`);
}

U kunt ook device.gatt.disconnect() bellen om uw web -app los te koppelen van het Bluetooth -apparaat. Dit zal bestaande gattserverdisconnected Event -luisteraars activeren. Merk op dat het de communicatie tussen Bluetooth Device niet stopt als een andere app al communiceert met het Bluetooth -apparaat. Bekijk het apparaat dat het monster loskoppelen en het automatische opnieuw verbindmonster om dieper te duiken.

Lees en schrijf naar Bluetooth -descriptors

Bluetooth GATT -descriptoren zijn attributen die een karakteristieke waarde beschrijven. Je kunt ze op een vergelijkbare manier lezen en schrijven als Bluetooth GATT -kenmerken.

Laten we bijvoorbeeld eens kijken hoe u de gebruikersbeschrijving van het meetinterval van de gezondheidsthermometer van het apparaat kunt lezen.

In het onderstaande voorbeeld is health_thermometer de gezondheidsthermometerdienst , measurement_interval het meetintervalkenmerk en gatt.characteristic_user_description de karakteristieke gebruikersbeschrijving descriptor .

navigator.bluetooth.requestDevice({ filters: [{ services: ['health_thermometer'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('health_thermometer'))
.then(service => service.getCharacteristic('measurement_interval'))
.then(characteristic => characteristic.getDescriptor('gatt.characteristic_user_description'))
.then(descriptor => descriptor.readValue())
.then(value => {
  const decoder = new TextDecoder('utf-8');
  console.log(`User Description: ${decoder.decode(value)}`);
})
.catch(error => { console.error(error); });

Nu we de gebruikersbeschrijving van het meetinterval van de gezondheidsthermometer van het apparaat hebben gelezen, laten we eens kijken hoe we het kunnen bijwerken en een aangepaste waarde schrijven.

navigator.bluetooth.requestDevice({ filters: [{ services: ['health_thermometer'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('health_thermometer'))
.then(service => service.getCharacteristic('measurement_interval'))
.then(characteristic => characteristic.getDescriptor('gatt.characteristic_user_description'))
.then(descriptor => {
  const encoder = new TextEncoder('utf-8');
  const userDescription = encoder.encode('Defines the time between measurements.');
  return descriptor.writeValue(userDescription);
})
.catch(error => { console.error(error); });

Monsters, demo's en codelabs

Alle onderstaande web Bluetooth -monsters zijn succesvol getest. Om deze monsters ten volle te genieten, raad ik u aan de [BLE Perifere Simulator Android -app] te installeren die een BLE -perifeer simuleert met een batterijservice, een hartslagdienst of een gezondheidsthermometer -service.

Beginner

  • Apparaatinformatie - Informatie over basisapparatuur ophalen van een BLE -apparaat.
  • Batterijniveau - Ophalen van batterij -informatie uit een BLE -apparaatinformatie advertentie -batterij.
  • Reset Energy - Reset Energy uitgegeven van een BLE -apparaat advertentie hartslag.
  • Karakteristieke eigenschappen - Toon alle eigenschappen van een specifiek kenmerk van een BLE -apparaat.
  • Meldingen - Start en stop karakteristieke meldingen van een BLE -apparaat.
  • Apparaat loskoppelen - Koppel los en ontvang op de hoogte van een ontkoppeling van een BLE -apparaat nadat u ermee aangesloten is.
  • Krijg kenmerken - Haal alle kenmerken van een geadverteerde service van een BLE -apparaat.
  • Ontvang descriptoren - Krijg alle descriptoren van een geadverteerde service van een BLE -apparaat.
  • Fabrikant Gegevensfilter - Haal basisinformatie op het gebied van een BLE -apparaat op dat overeenkomt met gegevens van de fabrikant.
  • Uitsluitingsfilters - Ophalen van basisinformatie van het apparaat uit een BLE -apparaat met basisuitsluitingsfilters.

Meerdere bewerkingen combineren

Bekijk ook onze samengestelde web Bluetooth -demo's en officiële Web Bluetooth -codelabs .

Bibliotheken

  • Web-Bluetooth-Utils is een NPM-module die enkele gemaksfuncties toevoegt aan de API.
  • Een Web Bluetooth API Shim is beschikbaar in Noble , de meest populaire knooppunt.js ble in centrale module. Hiermee kunt u Webpack/Browserify Noble zonder een Websocket -server of andere plug -ins.
  • Angular-WEB-Bluetooth is een module voor hoekige die alle boilerplate samenbrengt die nodig is om de Web Bluetooth API te configureren.

Hulpmiddelen

  • Ga aan de slag met Web Bluetooth is een eenvoudige web -app die alle JavaScript -boilerplate -code genereert om te beginnen met interactie met een Bluetooth -apparaat. Voer een apparaatnaam in, een service, een kenmerk, definieer de eigenschappen en u bent klaar om te gaan.
  • Als u al een Bluetooth -ontwikkelaar bent, genereert de Web Bluetooth -ontwikkelaarstudio -plug -in ook de Web Bluetooth JavaScript -code voor uw Bluetooth -apparaat.

Tips

Een Bluetooth Internals- pagina is beschikbaar in Chrome op about://bluetooth-internals zodat u alles kunt inspecteren over nabijgelegen Bluetooth-apparaten: status, services, kenmerken en descriptoren.

Screenshot van de interne pagina om Bluetooth in Chrome te debuggen
Interne pagina in Chrome voor het debuggen van Bluetooth -apparaten.

Ik raad ook aan om de officiële pagina Web Bluetooth -bugs te bekijken, omdat het debuggen van Bluetooth soms moeilijk kan zijn.

Wat is het volgende

Controleer eerst de browser- en platformimplementatiestatus om te weten welke delen van de web Bluetooth API momenteel worden geïmplementeerd.

Hoewel het nog steeds onvolledig is, is hier een voorproefje van wat te verwachten in de nabije toekomst:

  • Scannen op nabijgelegen BLE -advertenties zal plaatsvinden met navigator.bluetooth.requestLEScan() .
  • Een nieuw serviceadded -evenement volgt nieuw ontdekte Bluetooth Gatt -services, terwijl serviceremoved -evenement verwijderde evenement volgt. Een nieuw servicechanged -evenement zal ontslaan wanneer een kenmerk en/of descriptor wordt toegevoegd of verwijderd uit een Bluetooth Gatt -service.

Toon ondersteuning voor de API

Ben je van plan om de Web Bluetooth API te gebruiken? Uw publieke steun helpt het Chrome-team prioriteiten te stellen voor functies en laat andere browserleveranciers zien hoe belangrijk het is om deze te ondersteunen.

Stuur een tweet naar @chromiumdev met behulp van de hashtag #WebBluetooth en laat ons weten waar en hoe u deze gebruikt.

Bronnen

Erkenningen

Dank aan Kayce Basques voor het beoordelen van dit artikel. Hero Image door Sparkfun Electronics uit Boulder, VS.