Interfejs Web Bluetooth API umożliwia witrynom komunikowanie się z urządzeniami Bluetooth.
A co, jeśli powiem Ci, że witryny mogą komunikować się z bliskimi urządzeniami Bluetooth w sposób bezpieczny i nie naruszający prywatności? Dzięki temu monitory tętna, śpiewające żarówki, a nawet żółwie mogłyby wchodzić w interakcję bezpośrednio ze stroną internetową.
Do tej pory możliwość interakcji z urządzeniami Bluetooth była dostępna tylko w przypadku aplikacji przeznaczonych na konkretne platformy. Interfejs Web Bluetooth API ma na celu zmianę tego stanu rzeczy i wprowadza tę technologię również do przeglądarek internetowych.
Zanim zaczniemy
W tym dokumencie zakładamy, że masz podstawową wiedzę o tym, jak działa Bluetooth Low Energy (BLE) i profil atrybutów ogólnych.
Mimo że specyfikacja interfejsu Web Bluetooth API nie została jeszcze sfinalizowana, autorzy specyfikacji aktywnie poszukują entuzjastycznych deweloperów, którzy wypróbują ten interfejs API i prześlą opinie na temat specyfikacji oraz opinie na temat implementacji.
Podzbiór interfejsu API Bluetooth w internecie jest dostępny w ChromeOS, Chrome na Androida w wersji 6.0, Mac (Chrome w wersji 56) i Windows 10 (Chrome w wersji 70). Oznacza to, że możesz prosić i łączyć się z bliskimi urządzeniami Bluetooth Low Energy, czytać/pisać właściwości Bluetooth, otrzymywać powiadomienia GATT, wiedzieć, kiedy urządzenie Bluetooth zostało odłączone, a nawet czytać i pisać w opisach Bluetooth. Więcej informacji znajdziesz w tabeli Zgodność przeglądarek w MDN.
W przypadku Linuksa i starszych wersji Windowsa włącz flagę #experimental-web-platform-features
w about://flags
.
Dostępne w wersjach próbnych origin
Aby uzyskać jak najwięcej informacji zwrotnych od deweloperów korzystających z interfejsu Web Bluetooth API w praktyce, wcześniej dodaliśmy tę funkcję w Chrome 53 jako test wersji źródłowej na potrzeby ChromeOS, Androida i Maca.
W styczniu 2017 r. zakończyliśmy testowanie.
Wymagania dotyczące bezpieczeństwa
Aby zrozumieć kompromisy związane z bezpieczeństwem, przeczytaj wpis Model zabezpieczeń Bluetooth w internecie autorstwa Jeffreya Yasskina, inżyniera oprogramowania z zespołu Chrome, który pracuje nad specyfikacją interfejsu Web Bluetooth API.
Tylko HTTPS
Ten eksperymentalny interfejs API to potężna nowa funkcja dodana do sieci, dlatego jest dostępna tylko w bezpiecznych kontekstach. Oznacza to, że musisz skompilować aplikację z uwzględnieniem protokołu TLS.
Wymagane działanie użytkownika
Ze względów bezpieczeństwa wykrywanie urządzeń Bluetooth przez navigator.bluetooth.requestDevice
musi być aktywowane przez działanie użytkownika, takie jak dotknięcie lub kliknięcie myszką. Mowa o odbieraniu zdarzeń pointerup
, click
i touchend
.
button.addEventListener('pointerup', function(event) {
// Call navigator.bluetooth.requestDevice
});
Poznaj kod
Interfejs Web Bluetooth API w dużej mierze korzysta z obietnic w JavaScript. Jeśli nie znasz tych funkcji, zapoznaj się z tym świetnym samouczkiem. Kolejną rzeczą, która nie jest obsługiwana, są funkcje strzałki ECMAScript 2015.() => {}
Prośba o urządzenia Bluetooth
Ta wersja specyfikacji interfejsu Web Bluetooth API umożliwia stronom internetowym działającym w roli centralnej nawiązywanie połączeń z odległymi serwerami GATT przez połączenie BLE. Obsługuje komunikację między urządzeniami z Bluetooth 4.0 lub nowszym.
Gdy witryna prosi o dostęp do urządzeń w pobliżu za pomocą interfejsu navigator.bluetooth.requestDevice
, przeglądarka wyświetla użytkownikowi okno wyboru urządzenia, w którym może on wybrać jedno urządzenie lub anulować prośbę.
Funkcja navigator.bluetooth.requestDevice()
przyjmuje obowiązkowy obiekt, który definiuje filtry. Te filtry służą do zwracania tylko urządzeń, które pasują do niektórych reklamowanych usług Bluetooth GATT lub nazwy urządzenia.
Filtr usług
Aby na przykład zażądać urządzeń Bluetooth reklamujących usługę Bluetooth GATT Battery Service:
navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Jeśli usługa Bluetooth GATT nie znajduje się na liście standardowych usług Bluetooth GATT, możesz podać pełny identyfikator UUID Bluetooth lub jego skróconą wersję 16- lub 32-bitową.
navigator.bluetooth.requestDevice({
filters: [{
services: [0x1234, 0x12345678, '99999999-0000-1000-8000-00805f9b34fb']
}]
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Filtr według nazwy
Możesz też żądać urządzeń Bluetooth na podstawie nazwy urządzenia reklamowanego za pomocą klucza filtrów name
lub nawet prefiksu tej nazwy za pomocą klucza filtrów namePrefix
. Pamiętaj, że w tym przypadku musisz też zdefiniować klucz optionalServices
, aby uzyskać dostęp do usług nieobjętych filtrem usług. Jeśli tego nie zrobisz, później pojawi się błąd podczas próby uzyskania do nich dostępu.
navigator.bluetooth.requestDevice({
filters: [{
name: 'Francois robot'
}],
optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Filtr danych o producencie
Można też wysyłać żądania dotyczące urządzeń Bluetooth na podstawie danych o poszczególnych producentach, które są reklamowane za pomocą klucza filtrów manufacturerData
. Ten klucz jest tablicą obiektów z obowiązkowym kluczem identyfikatora firmy Bluetooth o nazwie companyIdentifier
. Możesz też podać prefiks danych, który odfiltruje dane producenta z urządzeń Bluetooth, których nazwy zaczynają się od tego prefiksu. Pamiętaj, że aby uzyskać dostęp do usług, które nie są uwzględnione w filtrze usług, musisz też zdefiniować klucz optionalServices
. Jeśli tego nie zrobisz, później, gdy spróbujesz uzyskać do nich dostęp, pojawi się błąd.
// 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); });
Maski można też używać z prefiksem danych, aby dopasowywać niektóre wzorce w danych producenta. Aby dowiedzieć się więcej, zapoznaj się z wyjaśnieniem filtrów danych Bluetooth.
Filtry wykluczania
Opcja exclusionFilters
w navigator.bluetooth.requestDevice()
pozwala wykluczyć niektóre urządzenia z selektora przeglądarek. Można go użyć do wykluczenia urządzeń, które pasują do szerszego filtra, ale nie są obsługiwane.
// 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); });
Brak filtrów
Na koniec, zamiast filters
, możesz użyć klawisza acceptAllDevices
, aby wyświetlić wszystkie urządzenia Bluetooth w pobliżu. Aby uzyskać dostęp do niektórych usług, musisz też określić klucz optionalServices
. Jeśli tego nie zrobisz, później, gdy spróbujesz uzyskać do nich dostęp, pojawi się błąd.
navigator.bluetooth.requestDevice({
acceptAllDevices: true,
optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Nawiązywanie połączenia z urządzeniem Bluetooth
Co zrobić, gdy masz BluetoothDevice
? Połącz się z odległym serwerem GATT Bluetooth, który zawiera definicje usług i charakterystyk.
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); });
Odczytywanie właściwości Bluetooth
Tutaj łączymy się z serwerem GATT zdalnego urządzenia Bluetooth. Teraz chcemy uzyskać główną usługę GATT i odczytać jej cechę. Spróbujmy na przykład odczytać bieżący poziom naładowania baterii urządzenia.
W przykładzie poniżej battery_level
to ujednolicony parametr Poziom baterii.
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); });
Jeśli używasz niestandardowej cechy GATT Bluetooth, możesz podać pełny identyfikator UUID Bluetooth lub krótki identyfikator 16- lub 32-bitowy w polu service.getCharacteristic
.
Pamiętaj, że możesz też dodać do cechy listenera zdarzenia characteristicvaluechanged
, aby obsługiwać odczyt jego wartości. Zapoznaj się z przykładem odczytu wartości właściwości, aby dowiedzieć się, jak opcjonalnie obsługiwać nadchodzące powiadomienia GATT.
…
.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);
}
Zapisywanie w charakterystyce Bluetooth
Zapisywanie danych w charakterystyce GATT Bluetooth jest tak samo proste jak ich odczytywanie. Tym razem użyjemy punktu kontrolnego tętna, aby zresetować wartość pola wydatkowanej energii na 0 na urządzeniu monitorującym tętno.
Zapewniam, że nie ma tu żadnej magii. Więcej informacji znajdziesz na stronie z opisem funkcji pomiaru tętna w aplikacji Punkty kardio.
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); });
Odbieranie powiadomień GATT
Teraz zobaczmy, jak otrzymywać powiadomienia, gdy na urządzeniu zmieni się wartość Pomiar tętna:
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
}
Plik Notifications Sample pokazuje, jak zatrzymać powiadomienia za pomocą stopNotifications()
i jak prawidłowo usunąć dodany odbiornik zdarzeń characteristicvaluechanged
.
Rozłączanie z urządzeniem Bluetooth
Aby zapewnić większą wygodę użytkownikom, możesz nasłuchiwać zdarzeń rozłączenia i zapraszać użytkowników do ponownego nawiązania połączenia:
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.`);
}
Możesz też zadzwonić na numer device.gatt.disconnect()
, aby odłączyć aplikację internetową od urządzenia Bluetooth. Spowoduje to wywołanie istniejących słuchaczy zdarzeń gattserverdisconnected
. Pamiętaj, że nie zatrzyma to komunikacji z urządzeniem Bluetooth, jeśli inna aplikacja już z nim komunikuje się. Aby dowiedzieć się więcej, zapoznaj się z przykładem DeviceDisconnectSample i AutomaticReconnectSample.
Odczytywanie i zapisywanie w opisach Bluetooth
Deskryptory GATT Bluetootha to atrybuty opisujące wartość charakterystyczną. Można je odczytywać i zapisywać w sposób podobny do właściwości GATT Bluetooth.
Zobaczmy na przykład, jak odczytać z opisu urządzenia opis interwału pomiarowego termometru stanu urządzenia.
W przykładzie poniżej health_thermometer
to usługa Termometr zdrowotny, measurement_interval
to charakterystyka Interval pomiaru, a gatt.characteristic_user_description
to opis tej charakterystyki w nazwanej przez użytkownika formie.
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); });
Teraz, gdy już znamy opis interwału pomiarowego w termometrze medycznym urządzenia, zobaczmy, jak go zaktualizować i wprowadzić wartość niestandardową.
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); });
Przykłady, demonstracje i ćwiczenia z programowania
Wszystkie wymienione poniżej próbki Web Bluetooth zostały przetestowane. Aby w pełni korzystać z tych próbek, zalecam zainstalowanie [Aplikacji BLE Peripheral Simulator] na Androida, która symuluje urządzenie peryferyjne BLE z usługą Battery Service, Heart Rate Service lub Health Thermometer Service.
Początkujący
- Informacje o urządzeniu – pobieranie podstawowych informacji o urządzeniu BLE.
- Poziom baterii – pobieranie informacji o baterii z urządzenia BLE reklamującego informacje o baterii.
- Reset Energy (Resetowanie energii) – zresetuj energię zużytą przez urządzenie BLE wyświetlające tętno.
- Właściwości cech – wyświetla wszystkie właściwości określonej cechy urządzenia BLE.
- Powiadomienia – uruchamianie i zatrzymywanie powiadomień o charakterystyce z urządzenia BLE.
- Rozłączanie urządzenia – rozłączanie i otrzymywanie powiadomienia o rozłączeniu urządzenia BLE po połączeniu z nim.
- Get Characteristics (Uzyskaj właściwości) – umożliwia uzyskanie wszystkich właściwości reklamowanej usługi z urządzenia BLE.
- Get Descriptors (Uzyskaj opisy) – pobiera wszystkie opisy cech reklamowanej usługi z urządzenia BLE.
- Filtr danych producenta – pobiera podstawowe informacje o urządzeniu BLE, które pasują do danych producenta.
- Filtry wykluczeń – pobieranie podstawowych informacji o urządzeniu BLE z użyciem podstawowych filtrów wykluczeń.
Łączenie wielu operacji
- Właściwości GAP – umożliwiają uzyskanie wszystkich właściwości GAP urządzenia BLE.
- Charakterystyka informacji o urządzeniu – pobieranie wszystkich informacji o urządzeniu BLE.
- Utrata połączenia – ustaw funkcję Alert Level urządzenia BLE (readValue & writeValue).
- Odkrywanie usług i ich właściwości – umożliwia odkrywanie wszystkich dostępnych usług podstawowych i ich właściwości na urządzeniu BLE.
- Automatyczne ponowne łączenie – ponowne połączenie z odłączonym urządzeniem BLE za pomocą algorytmu wykładniczego.
- Read Characteristic Value Changed (Odczyt wartości zmienionej właściwości) – odczyt poziomu naładowania baterii i powiadamianie o zmianach na urządzeniu BLE.
- Read Descriptors (Odczytywanie opisów) – odczytywanie wszystkich opisów cech usługi z urządzenia BLE.
- Write Descriptor (Zapisz Descriptor) – zapisz w przystawce „Characteristic User Description” (Opis użytkownika cechy) na urządzeniu BLE.
Zapoznaj się też z wybranymi demonstracjami Bluetootha w internecie i z oficjalnymi Codelab dotyczącymi Bluetootha w internecie.
Biblioteki
- web-bluetooth-utils to moduł npm, który dodaje do interfejsu API kilka przydatnych funkcji.
- Interfejs API Web Bluetooth jest dostępny w noble, najpopularniejszym module Node.js dla BLE. Dzięki temu możesz używać webpacka lub browserify w Noble bez konieczności korzystania z serwera WebSocket ani innych wtyczek.
- angular-web-bluetooth to moduł dla Angular, który abstrahuje wszystkie szablony potrzebne do konfigurowania interfejsu Web Bluetooth API.
Narzędzia
- Wprowadzenie do Bluetootha internetowego to prosta aplikacja internetowa, która wygeneruje cały kod JavaScript, aby umożliwić interakcję z urządzeniem Bluetooth. Wpisz nazwę urządzenia, usługę, cechę, zdefiniuj ich właściwości i gotowe.
- Jeśli jesteś już deweloperem Bluetooth, wtyczka Web Bluetooth Developer Studio wygeneruje również kod JavaScriptu Web Bluetooth na Twoje urządzenie Bluetooth.
Wskazówki
W Chrome na stronie Bluetooth Internals (about://bluetooth-internals
) możesz sprawdzić wszystkie informacje o blisko położonych urządzeniach Bluetooth: stan, usługi, cechy i deskryptory.

Zalecamy też zapoznanie się z oficjalną stroną Jak zgłosić błąd Bluetooth w internetowym systemie Bluetooth, ponieważ debugowanie Bluetooth może być czasami trudne.
.Co dalej?
Aby dowiedzieć się, które części interfejsu Web Bluetooth API są obecnie wdrażane, sprawdź najpierw stan wdrożenia przeglądarki i platformy.
Chociaż lista jest jeszcze niekompletna, przedstawiamy kilka przykładów tego, czego możesz się spodziewać w najbliższej przyszłości:
navigator.bluetooth.requestLEScan()
będzie skanować reklamy BLE w pobliżu.- Nowe zdarzenie
serviceadded
będzie rejestrować nowo wykryte usługi GATT Bluetooth, a zdarzenieserviceremoved
– usunięte. Nowe zdarzenieservicechanged
zostanie wywołane, gdy jakakolwiek cecha lub opis zostanie dodany lub usunięty z usługi GATT Bluetooth.
Pokaż pomoc dotyczącą interfejsu API
Zamierzasz używać interfejsu Web Bluetooth API? Twoja publiczna pomoc pomaga zespołowi Chrome ustalać priorytety funkcji i pokazuje innym dostawcom przeglądarek, jak ważne jest wspieranie tych funkcji.
Wyślij tweeta do @ChromiumDev, używając hashtaga #WebBluetooth
i podaj, gdzie i jak go używasz.
Zasoby
- Stack Overflow
- Stan funkcji Chrome
- Błędy implementacji w Chrome
- Specyfikacja Web Bluetooth
- Problemy ze specyfikacją na GitHubie
- Aplikacja BLE Peripheral Simulator
Podziękowania
Dziękujemy Kayce Basques za sprawdzenie tego artykułu. Obraz główny firmy SparkFun Electronics z Boulder w USA.