A API Web Bluetooth permite que sites se comuniquem com dispositivos Bluetooth.
E se eu disser que sites podem se comunicar com dispositivos Bluetooth por perto? de forma segura e preservando a privacidade? Dessa forma, os monitores de frequência cardíaca, cantando lâmpadas e até tartarugas poderiam interagir diretamente com um site.
Até agora, a capacidade de interagir com dispositivos Bluetooth era possível apenas para aplicativos específicos da plataforma. O objetivo da API Web Bluetooth é mudar isso e também o leva para navegadores da Web.
Antes de começar
Este documento pressupõe que você tenha algum conhecimento básico sobre o uso do Bluetooth Low Energia (BLE) e o Perfil de atributo genérico funcionam.
Embora a especificação da API Web Bluetooth ainda não esteja finalizada, ela os autores estão procurando ativamente desenvolvedores interessados para testar essa API e envie feedback sobre as especificações e sobre a implementação.
Um subconjunto da API Web Bluetooth está disponível no ChromeOS e no Chrome para Android 6.0, Mac (Chrome 56) e Windows 10 (Chrome 70). Isso significa que você deve ser capaz para solicitar e se conectar a dispositivos Bluetooth de baixa energia perto de você, ler/gravar características do Bluetooth, receber notificações GATT, saber quando um dispositivo Bluetooth é desconectado, e até mesmo ler e gravar no Descritores Bluetooth. Consulte a tabela Compatibilidade do navegador da MDN para saber mais informações imprecisas ou inadequadas.
Para Linux e versões anteriores do Windows, ative a
Sinalização #experimental-web-platform-features
em about://flags
.
Disponível para testes de origem
Para obter o máximo de feedback possível de desenvolvedores que usam a Web API Bluetooth em campo, o Chrome já adicionou esse recurso ao Chrome 53 como um teste de origem para ChromeOS, Android e Mac.
O teste terminou em janeiro de 2017.
Requisitos de segurança
Para entender as desvantagens de segurança, recomendo o curso Web Bluetooth Security Model feita por Jeffrey Yasskin, engenheiro de software da equipe do Chrome, trabalhando com a especificação da API Web Bluetooth.
Somente HTTPS
Como essa API experimental é um novo e poderoso recurso adicionado à Web, ela é disponibilizado apenas para contextos seguros. Isso significa que você precisará criar com TLS em mente.
Gesto do usuário necessário
Como um recurso de segurança, descobrir dispositivos Bluetooth com
navigator.bluetooth.requestDevice
precisa ser acionado por um gesto do usuário, como
como um toque ou um clique do mouse. Estamos falando sobre ouvir
pointerup
, click
e touchend
.
button.addEventListener('pointerup', function(event) {
// Call navigator.bluetooth.requestDevice
});
Entrar no código
A API Web Bluetooth depende muito de promessas JavaScript. Se você não estiver
se familiarizar com eles, confira este ótimo tutorial de promessas. Mais uma coisa,
() => {}
são funções de seta do ECMAScript 2015.
Solicitar dispositivos Bluetooth
Essa versão da especificação da API Web Bluetooth permite que sites, em execução no o papel Central, para se conectar aos servidores GATT remotos por uma conexão BLE. Ela suporta a comunicação entre dispositivos que implementam Bluetooth 4.0 ou posterior.
Quando um site solicita acesso a dispositivos próximos usando
navigator.bluetooth.requestDevice
, o navegador solicita ao usuário um dispositivo
onde poderá escolher um dispositivo ou cancelar a solicitação.
A função navigator.bluetooth.requestDevice()
usa um objeto obrigatório que
define filtros. Esses filtros são usados para retornar somente dispositivos que correspondem a alguns
os serviços GATT anunciados e/ou o nome do dispositivo.
Filtro de serviços
Por exemplo, para solicitar dispositivos Bluetooth que anunciam o Bluetooth GATT Serviço da bateria:
navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Se o seu Bluetooth GATT Service não estiver na lista de dispositivos Bluetooth padronizados serviços GATT, é possível fornecer o UUID completo do Bluetooth ou um Formato de 16 ou 32 bits.
navigator.bluetooth.requestDevice({
filters: [{
services: [0x1234, 0x12345678, '99999999-0000-1000-8000-00805f9b34fb']
}]
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Filtro de nome
Você também pode solicitar dispositivos Bluetooth com base no nome do dispositivo anunciado
usando a chave de filtros name
ou até mesmo um prefixo desse nome com a namePrefix
chave de filtros. Nesse caso, você também vai precisar definir o
optionalServices
para acessar qualquer serviço não incluído em uma
filtro de serviço. Caso contrário, você vai receber uma mensagem de erro mais tarde ao tentar acessar
para resolvê-los com rapidez.
navigator.bluetooth.requestDevice({
filters: [{
name: 'Francois robot'
}],
optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Filtro de dados do fabricante
Também é possível solicitar dispositivos Bluetooth com base no fabricante
dados específicos anunciados com a chave de filtros manufacturerData
. Esta chave
é uma matriz de objetos com uma chave de identificador de empresa Bluetooth obrigatória chamada
companyIdentifier
Você também pode fornecer um prefixo de dados que filtra
dados do fabricante de dispositivos Bluetooth que começam com ele. Observe que você
também precisa definir a chave optionalServices
para poder acessar qualquer serviço
não incluídos em um filtro de serviço. Caso contrário, você receberá um erro mais tarde, quando
tentando acessá-las.
// 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); });
Uma máscara também pode ser usada com um prefixo de dados para corresponder a alguns padrões em dados do fabricante. Confira a explicação sobre filtros de dados Bluetooth para saber mais mais.
Filtros de exclusão
A opção exclusionFilters
em navigator.bluetooth.requestDevice()
permite
exclua alguns dispositivos do seletor de navegador. Ele pode ser usado para excluir
dispositivos que correspondem a um filtro mais amplo, mas não são compatíveis.
// 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); });
Sem filtros
Por fim, em vez de filters
, é possível usar a tecla acceptAllDevices
para mostrar todos
dispositivos Bluetooth por perto. Você também vai precisar definir o optionalServices
para acessar alguns serviços. Caso contrário, uma mensagem de erro será exibida.
ao tentar acessá-las.
navigator.bluetooth.requestDevice({
acceptAllDevices: true,
optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Conectar-se a um dispositivo Bluetooth
O que fazer agora que você tem um BluetoothDevice
? Vamos nos conectar
Servidor GATT remoto Bluetooth que mantém o serviço e as características
e definições.
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); });
Ler uma característica do Bluetooth
Aqui, conectamos ao servidor GATT do dispositivo Bluetooth remoto. Agora vamos desejar obter um serviço GATT primário e ler uma característica que pertence ao esse serviço. Vamos tentar, por exemplo, ler o nível de carga atual do da bateria do dispositivo.
No exemplo a seguir, battery_level
é o nível de bateria padronizado
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); });
Se você usa uma característica GATT personalizada do Bluetooth, pode fornecer o
um UUID Bluetooth completo ou uma forma curta de 16 ou 32 bits para
service.getCharacteristic
:
Também é possível adicionar um listener de eventos characteristicvaluechanged
em um
para processar a leitura do valor dele. Confira a Característica de leitura
Exemplo de valor alterado para ver como lidar opcionalmente com os próximos GATTs
as notificações.
…
.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);
}
Gravar em uma característica do Bluetooth
Gravar em uma característica do Bluetooth GATT é tão fácil quanto ler. Desta vez, usaremos o Ponto de Controle de Frequência Cardíaca para redefinir o valor de Energia gasta como 0 em um dispositivo de monitoramento de frequência cardíaca.
Prometo não ter mágica aqui. Tudo isso está explicado no tópico Controle de frequência cardíaca página "Característica do ponto".
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); });
Receber notificações GATT
Agora, vejamos como ser notificados quando a Medição de frequência cardíaca mudanças características no 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
}
O Exemplo de notificações mostra como parar as notificações com
stopNotifications()
e remova corretamente o characteristicvaluechanged
adicionado.
listener de eventos.
Desconectar-se de um dispositivo Bluetooth
Para oferecer uma melhor experiência ao usuário, você pode detectar eventos de desconexão e convide o usuário a se reconectar:
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.`);
}
Você também pode chamar device.gatt.disconnect()
para desconectar seu app da Web da
dispositivo Bluetooth. Isso vai acionar o evento gattserverdisconnected
atual
os listeners. Observe que ele NÃO interromperá a comunicação do dispositivo Bluetooth se outro
app já está se comunicando com o dispositivo Bluetooth. Acesse a página Dispositivos
Desconectar o exemplo e Exemplo de reconexão automática para saber mais.
Ler e gravar descritores Bluetooth
Os descritores Bluetooth GATT são atributos que descrevem um valor de característica. Eles podem ser lidos e gravados de maneira semelhante ao Bluetooth GATT e as características determinantes.
Vamos ver, por exemplo, como ler a descrição do usuário da medição do termômetro de integridade do dispositivo.
No exemplo abaixo, health_thermometer
é o serviço Termômetro de saúde.
measurement_interval
, a característica do intervalo de medição, e
gatt.characteristic_user_description
a Descrição característica do usuário
descritor.
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); });
Agora que lemos a descrição do usuário sobre o intervalo de medição do termômetro de integridade do dispositivo, vamos aprender a atualizá-lo e criar um .
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); });
Amostras, demonstrações e codelabs
Todos os exemplos de Bluetooth da Web abaixo foram testados. Para aproveitar o máximo possível, recomendamos que você instale o [BLE Peripheral Simulator, app Android] que simula um periférico de BLE com um serviço de bateria, uma frequência cardíaca serviço ou um serviço de termômetro de saúde.
Iniciante
- Informações do dispositivo: recupere informações básicas de um dispositivo BLE.
- Nível da bateria: recupere as informações da bateria de um dispositivo BLE que anuncie informações sobre a bateria.
- Redefinir energia: redefine a energia gasta de um dispositivo BLE que anuncia a frequência cardíaca.
- Propriedades de características: exibe todas as propriedades de uma característica específica de um dispositivo BLE.
- Notificações: inicia e interrompe notificações características de um dispositivo BLE.
- Dispositivo desconectado: se um dispositivo BLE for desconectado, recebe uma notificação quando se conecta a ele.
- Receber características: colete todas as características de um serviço anunciado de um dispositivo BLE.
- Acessar descritores: acessar todas as características descritores de um serviço anunciado de um dispositivo BLE.
- Filtro de dados do fabricante: recupere informações básicas de um dispositivo BLE que corresponda aos dados do fabricante.
- Filtros de exclusão: recupere informações básicas de um dispositivo BLE com filtros de exclusão básicos.
Combinar várias operações
- GAP Characteristics: acessar todas as características do GAP de um dispositivo BLE.
- Características das informações do dispositivo: acesse todas as características das informações do dispositivo de um dispositivo BLE.
- Perda de vínculo: defina a característica do nível de alerta de um dispositivo BLE (readValue e writeValue).
- Descubra serviços e Características: descubra todos os serviços principais acessíveis e as características deles em um dispositivo BLE.
- Reconexão automática: reconecte a um dispositivo BLE desconectado usando um algoritmo de espera exponencial.
- Ler valor de característica modificado: lê o nível de bateria e recebe notificações sobre mudanças em um dispositivo BLE.
- Ler descritores: ler todos os descritores de características de um serviço de um dispositivo BLE.
- Escrever descritor: escreva como "Descrição característica do usuário" em um dispositivo BLE.
Confira também nossas demonstrações selecionadas do Web Bluetooth e os codelabs oficiais do Web Bluetooth.
Bibliotecas
- O web-bluetooth-utils é um módulo npm que adiciona algumas funções de conveniência ao a API.
- Um paliativo da API Web Bluetooth está disponível no noble, o BLE mais usado do Node.js. no módulo central. Isso permite usar o webpack/browserify noble sem a necessidade de para um servidor WebSocket ou outros plug-ins.
- O angular-web-bluetooth é um módulo para o Angular que abstrai todos os necessário para configurar a API Web Bluetooth.
Ferramentas
- O Get Started with Web Bluetooth é um app da Web simples que gera todos código boilerplate de JavaScript para começar a interagir com um dispositivo Bluetooth. Digite um nome de dispositivo, um serviço, uma característica, defina as propriedades e está tudo pronto.
- Se você já é um desenvolvedor Bluetooth, o Web Bluetooth Developer Studio Plug-in também gera o código JavaScript do Web Bluetooth para o seu dispositivo Bluetooth.
Dicas
Uma página Bluetooth Internals está disponível no Chrome em
about://bluetooth-internals
para inspecionar tudo nas proximidades
Dispositivos Bluetooth: status, serviços, características e descritores.
Também recomendo consultar o guia oficial Como registrar bugs do Web Bluetooth (em inglês). porque a depuração do Bluetooth pode ser difícil.
A seguir
Verifique o status de implementação do navegador e da plataforma primeiro para saber quais partes da API Web Bluetooth estão em fase de implementação.
Embora ele ainda não esteja completo, aqui está uma prévia do que esperar futuro:
- Procura de anúncios BLE nas proximidades
vai acontecer com
navigator.bluetooth.requestLEScan()
. - Um novo evento
serviceadded
vai rastrear serviços GATT recém-descobertos do Bluetooth enquanto o eventoserviceremoved
vai acompanhar os removidos. Um novo dispositivoservicechanged
será acionado quando uma característica e/ou descritor for adicionado ou removido de um serviço Bluetooth GATT.
Mostrar suporte à API
Você pretende usar a API Web Bluetooth? Seu apoio público ajuda a equipe do Chrome priorizar recursos e mostrar a outros fornecedores de navegador como é fundamental oferecer suporte a eles.
Envie um tweet para @ChromiumDev usando a hashtag
#WebBluetooth
e informe onde e como você o utiliza.
Recursos
- Stack Overflow (em inglês)
- Status do recurso do Chrome
- Bugs de implementação do Chrome
- Especificações do Web Bluetooth
- Problemas de especificação no GitHub (link em inglês)
- App simulador de periférico BLE
Agradecimentos
Agradecemos a Kayce Basques por revisar este artigo. Imagem principal da SparkFun Electronics de Boulder, EUA.