La API de Web Bluetooth permite que los sitios web se comuniquen con dispositivos Bluetooth.
¿Y si te dijera que los sitios web pueden comunicarse con dispositivos Bluetooth cercanos? de forma segura y privada? Así, monitores de frecuencia cardíaca, canto las bombillas y las tortugas podrían interactuar directamente con un sitio web.
Hasta ahora, era posible interactuar con dispositivos Bluetooth solo para apps específicas de la plataforma. La API de Web Bluetooth tiene como objetivo cambiar esto y también la lleva a los navegadores web.
Antes de comenzar
En este documento, se asume que tienes conocimientos básicos sobre cómo el Bluetooth de bajo consumo Energy (BLE) y el perfil de atributos genéricos funcionan.
Si bien la especificación de la API de Web Bluetooth aún no está finalizada, la especificación autores buscan activamente desarrolladores entusiastas para probar esta API y proporcionar comentarios sobre las especificaciones y comentarios sobre la implementación.
Hay un subconjunto de la API de Web Bluetooth disponible en ChromeOS y Chrome para Android. 6.0, Mac (Chrome 56) y Windows 10 (Chrome 70). Esto significa que deberías poder para solicitar y conectarse a dispositivos Bluetooth de bajo consumo cercanos funciones de Bluetooth de lectura y escritura, recibir notificaciones GATT, saber cuando un dispositivo Bluetooth se desconecta e incluso lectura y escritura en descriptores de Bluetooth. Consulta la tabla Compatibilidad con navegadores de MDN para obtener más información información.
Para Linux y versiones anteriores de Windows, habilita el
La marca #experimental-web-platform-features
en about://flags
.
Disponible para pruebas de origen
Para obtener la mayor cantidad de comentarios posible de los desarrolladores que usan la Web API de Bluetooth en el campo, Chrome ya agregó esta función en Chrome. 53 como prueba de origen para ChromeOS, Android y Mac.
La prueba finalizó correctamente en enero de 2017.
Requisitos de seguridad
Para comprender las compensaciones de seguridad, te recomiendo la Web Bluetooth Security del modelo de Jeffrey Yasskin, un ingeniero de software del equipo de Chrome, trabajando en la especificación de la API de Web Bluetooth.
Solo HTTPS
Debido a que esta API experimental es una nueva y potente función que se agrega a la Web, es se ponen a disposición solo en contextos seguros. Esto significa que deberás compilar con TLS en mente.
Se requiere un gesto del usuario
Como función de seguridad, descubrir dispositivos Bluetooth con
navigator.bluetooth.requestDevice
debe activarse mediante un gesto del usuario, como
como un toque o un clic del mouse. Hablamos de escuchar
Eventos pointerup
, click
y touchend
.
button.addEventListener('pointerup', function(event) {
// Call navigator.bluetooth.requestDevice
});
Ingresar al código
La API de Web Bluetooth depende en gran medida de las promesas de JavaScript. Si no eres
consulta este excelente instructivo sobre promesas. Una cosa más:
() => {}
son funciones de flecha de ECMAScript 2015.
Solicita dispositivos Bluetooth
Esta versión de la especificación de la API de Web Bluetooth permite el uso de sitios web que se ejecuten en la función central, para conectarse a servidores GATT remotos a través de una conexión BLE. Integra es compatible con la comunicación entre dispositivos que implementan Bluetooth 4.0 o versiones posteriores.
Cuando un sitio web solicita acceso a dispositivos cercanos usando
navigator.bluetooth.requestDevice
, el navegador solicita al usuario que cuente con un dispositivo.
con el que puede elegir un dispositivo o cancelar la solicitud.
La función navigator.bluetooth.requestDevice()
toma un objeto obligatorio que
define filtros. Estos filtros se usan para devolver solo los dispositivos que coinciden con algunos
los servicios de Bluetooth GATT anunciados o el nombre del dispositivo.
Filtro de servicios
Por ejemplo, para solicitar dispositivos Bluetooth que anuncien el estándar Bluetooth GATT Servicio de batería:
navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Si tu servicio Bluetooth GATT no se encuentra en la lista del servicio de Bluetooth estandarizado, haz lo siguiente: GATT, puedes proporcionar el UUID de Bluetooth completo o un formato de 16 o 32 bits.
navigator.bluetooth.requestDevice({
filters: [{
services: [0x1234, 0x12345678, '99999999-0000-1000-8000-00805f9b34fb']
}]
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Filtro por nombre
También puedes solicitar dispositivos Bluetooth según el nombre del dispositivo que se anuncia
con la clave de filtros name
o incluso un prefijo de este nombre con namePrefix
Filtros. Ten en cuenta que, en este caso, también deberás definir
optionalServices
para poder acceder a cualquier servicio no incluido en una
filtro de servicio. De lo contrario, recibirás un mensaje de error más adelante cuando intentes acceder.
de ellos.
navigator.bluetooth.requestDevice({
filters: [{
name: 'Francois robot'
}],
optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Filtro de datos del fabricante
También es posible solicitar dispositivos Bluetooth según el fabricante
datos específicos que se anuncian con la clave de filtros manufacturerData
Esta llave
es un array de objetos con una clave obligatoria de identificador Bluetooth de la empresa llamada
companyIdentifier
También puedes proporcionar un prefijo de datos que filtre
datos del fabricante de dispositivos Bluetooth que comienzan con el dispositivo. Ten en cuenta que
también debes definir la clave optionalServices
para poder acceder a cualquier servicio
no están incluidas en un filtro de servicio. De no ser así, recibirás un mensaje de error más adelante cuando
para intentar acceder a ellos.
// 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); });
También se puede usar una máscara con un prefijo de datos para hacer coincidir algunos patrones en datos del fabricante. Consulta la explicación sobre los filtros de datos de Bluetooth para obtener más información. más.
Filtros de exclusión
La opción exclusionFilters
en navigator.bluetooth.requestDevice()
te permite
excluyes algunos dispositivos
del selector del navegador. Se puede usar para excluir
que coinciden con un filtro más amplio, pero que no son compatibles.
// 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); });
Sin filtros
Por último, en lugar de filters
, puedes usar la tecla acceptAllDevices
para mostrar todo
dispositivos Bluetooth cercanos. También deberás definir el objeto optionalServices
para poder acceder a algunos servicios. De lo contrario, recibirás un mensaje de error más adelante
al intentar acceder a ellos.
navigator.bluetooth.requestDevice({
acceptAllDevices: true,
optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Conexión a un dispositivo Bluetooth
¿Qué puedes hacer ahora que tienes un BluetoothDevice
? Vamos a conectarnos con el
Servidor GATT con Bluetooth remoto que contiene el servicio y las características
definiciones
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); });
Leer una característica de Bluetooth
Aquí nos conectamos al servidor GATT del dispositivo Bluetooth remoto. Ahora, querrán obtener un servicio GATT principal y leer una característica que pertenezca a este servicio. Intentemos, por ejemplo, leer el nivel de carga actual del la batería del dispositivo.
En el siguiente ejemplo, battery_level
es el nivel de batería estandarizado
Característica.
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); });
Si utilizas una característica personalizada de Bluetooth GATT, puedes proporcionar el
UUID completo de Bluetooth o un formulario corto de 16 o 32 bits para
service.getCharacteristic
Ten en cuenta que también puedes agregar un objeto de escucha de eventos characteristicvaluechanged
en un
característica para manejar la lectura de su valor. Consulta la Característica de lectura
Ejemplo de cambio de valor para ver cómo controlar opcionalmente las próximas operaciones de GATT
notificaciones.
…
.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);
}
Escribe en una característica de Bluetooth
Escribir en una característica GATT de Bluetooth es tan fácil como leerlo. Esta vez, usemos el Punto de control de frecuencia cardíaca para restablecer el valor de Energía gastada en 0 en un monitor de frecuencia cardíaca.
Te prometo que no hay magia en esto. Todo se explica en la sección Control de la frecuencia cardíaca Página Característica del punto
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); });
Recibir notificaciones GATT
Ahora, veamos cómo recibir una notificación cuando se realiza la medición del ritmo cardíaco cambios característicos en el dispositivo:
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
}
El ejemplo de notificaciones te muestra cómo detener las notificaciones con
stopNotifications()
y quita correctamente el characteristicvaluechanged
agregado.
objeto de escucha de eventos.
Cómo desconectarse de un dispositivo Bluetooth
Para brindar una mejor experiencia del usuario, te recomendamos que escuches los eventos de desconexión e invita al usuario a volver a conectarse:
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.`);
}
También puedes llamar a device.gatt.disconnect()
para desconectar tu aplicación web desde la
dispositivo Bluetooth. Esto activará un evento gattserverdisconnected
existente
objetos de escucha. Ten en cuenta que NO detendrá la comunicación con dispositivos Bluetooth si otro
La app ya se está comunicando con el dispositivo Bluetooth. Consulta la página del dispositivo
Desconectar Sample y Automatic Reconnect Sample para obtener más información
Leer y escribir en descriptores de Bluetooth
Los descriptores de Bluetooth GATT son atributos que describen el valor de una característica. Puedes leerlas y escribirlas de forma similar a Bluetooth GATT. del usuario.
Veamos, por ejemplo, cómo leer la descripción del usuario de la medición del termómetro de salud del dispositivo.
En el siguiente ejemplo, health_thermometer
es el servicio de Termómetro de salud.
measurement_interval
la característica de intervalo de medición
gatt.characteristic_user_description
la descripción de características del usuario
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); });
Ahora que leímos la descripción del usuario del intervalo de medición de del termómetro de salud del dispositivo, veamos cómo actualizarlo y escribir un código valor.
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); });
Ejemplos, demostraciones y codelabs
Se probaron correctamente todos los ejemplos de Web Bluetooth que aparecen a continuación. Para disfrutar todas las muestras de código, te recomiendo instalar el [Simulador de periféricos BLE Android App] que simula un periférico BLE con un servicio de batería, una función o un servicio de Termómetro de salud.
Principiante
- Device Info: Recupera información básica del dispositivo desde un dispositivo BLE.
- Nivel de batería: Muestra información sobre la batería de un dispositivo BLE que anuncia información sobre la batería.
- Restablecer energía: Restablece la energía gastada por un dispositivo BLE que anuncia frecuencia cardíaca.
- Propiedades de las características: Muestran todas las propiedades de una característica específica de un dispositivo BLE.
- Notificaciones: Permite iniciar y detener las notificaciones de características desde un dispositivo BLE.
- Desconexión del dispositivo: Desconecta un dispositivo BLE y recibe notificaciones de esta después de conectarlo.
- Obtener características: Obtiene todas las características de un servicio anunciado desde un dispositivo BLE.
- Obtener descriptores: Obtener todas las características descriptores de servicio anunciados desde un dispositivo BLE.
- Filtro de datos del fabricante: Recupera información básica del dispositivo de un dispositivo BLE que coincide con los datos del fabricante.
- Filtros de exclusión: Recupera información básica del dispositivo de un dispositivo BLE que incluye filtros de exclusión básicos.
Cómo combinar varias operaciones
- Características de GAP: Obtén todas las características de GAP de un dispositivo BLE.
- Device Information Characteristics: Obtén todas las características de la información del dispositivo de un dispositivo BLE.
- Link Loss: Establece la característica del nivel de alerta de un dispositivo BLE (readValue y writeValue).
- Descubre servicios y Características: Descubre todos los servicios principales accesibles y sus características desde un dispositivo BLE.
- Reconexión automática: Vuelve a conectarte a un dispositivo BLE desconectado mediante un algoritmo de retirada exponencial.
- Read Characteristic Value Changed: Lee el nivel de batería y recibe notificaciones sobre los cambios que se realicen en un dispositivo BLE.
- Leer descriptores: Lee todos los descriptores de las características de un servicio desde un dispositivo BLE.
- Escribe el descriptor: escribe al descriptor "Descripción de la característica del usuario". en un dispositivo BLE.
Consulta también nuestras demostraciones seleccionadas de Bluetooth web y Codelabs oficiales de Bluetooth web.
Bibliotecas
- web-bluetooth-utils es un módulo de npm que agrega algunas funciones útiles a la API.
- Hay disponible una corrección de compatibilidad de la API de Web Bluetooth en noble, el BLE más popular de Node.js módulo central. Esto te permite empaquetar noble y navegar por la Web sin la necesidad para un servidor de WebSocket o para otros complementos.
- angular-web-Bluetooth es un módulo de Angular que abstrae código estándar necesario para configurar la API de Web Bluetooth.
Herramientas
- Get Started with Web Bluetooth es una aplicación web sencilla que generará el código estándar de JavaScript para comenzar a interactuar con un dispositivo Bluetooth. Ingresa un nombre de dispositivo, un servicio y una característica, define sus propiedades y estás listo para comenzar.
- Si ya eres desarrollador de Bluetooth, el sitio Web Bluetooth Developer Studio Plugin también generará el código JavaScript de Bluetooth web para tu dispositivo Bluetooth.
Sugerencias
En Chrome, hay una página sobre componentes internos de Bluetooth.
about://bluetooth-internals
para que puedas inspeccionar todo sobre los dispositivos cercanos
Dispositivos Bluetooth: estado, servicios, características y descriptores
También te recomendamos que consultes el artículo oficial Cómo informar errores de Web Bluetooth. ya que depurar Bluetooth puede ser difícil.
¿Qué sigue?
Verifica primero el estado de implementación del navegador y la plataforma para saber qué partes de la API de Web Bluetooth se están implementando.
Aunque todavía está incompleto, aquí tienes un adelanto de lo que puedes esperar en futuro:
- Cómo buscar anuncios BLE cercanos
ocurrirá con
navigator.bluetooth.requestLEScan()
. - Un nuevo evento
serviceadded
hará un seguimiento de los servicios de Bluetooth GATT recién descubiertos mientras queserviceremoved
evento hará un seguimiento de las que se quitaron. Un nuevoservicechanged
evento se activará cuando se agregue cualquier característica o descriptor eliminado de un servicio Bluetooth GATT.
Demuestra compatibilidad con la API
¿Planeas usar la API de Web Bluetooth? Tu asistencia pública ayuda al equipo de Chrome prioriza funciones y muestra a otros proveedores de navegadores la importancia de admitirlas.
Envía un tweet a @ChromiumDev con el hashtag
#WebBluetooth
y cuéntanos dónde y cómo la usas.
Recursos
- Stack Overflow
- Estado de las funciones de Chrome
- Errores en la implementación de Chrome
- Especificaciones de Bluetooth web
- Problemas de especificaciones en GitHub
- App de simulador de periféricos BLE
Agradecimientos
Agradecemos a Kayce Basques por revisar este artículo. Imagen hero de SparkFun Electronics de Boulder, EE.UU..