O objetivo deste BLOG é dar uma ideia geral do conceitos de como gerar um APP BLE para IOSIntrodução ao desenvolvimento móvel BLE [iOS]
Este tutorial representa uma pequena parte de um curso completo sobre desenvolvimento de BLE para iOS na Bluetooth Developer Academy. O curso foi desenvolvido em parceria com Anas Imtiaz , PhD .
Neste tutorial, examinaremos o desenvolvimento de aplicativos para iPhone / iPad que fazem interface com um periférico Bluetooth Low Energy para enviar / receber dados.
Começaremos analisando o Core Bluetooth , uma estrutura fornecida pela Apple para facilitar o desenvolvimento do BLE por meio do uso de APIs para executar ações diferentes. Também veremos o processo de configuração de um projeto no Xcode para o desenvolvimento do BLE, analisando os estágios de configuração para o uso inicial e levando em consideração o tratamento de permissões para diferentes versões do iOS.
Depois de configurar o fluxo de trabalho, mergulharemos no mundo das principais APIs Bluetooth e codificaremos nosso caminho para desenvolver um aplicativo capaz de:
- Digitalize a área para encontrar os diferentes periféricos BLE
- Exibir informações sobre os periféricos digitalizados
- Conecte-se a um periférico específico
IMPORTANTE : não abordaremos a criação da interface do usuário neste tutorial e focaremos estritamente em começar o desenvolvimento do BLE. Em vez disso, usaremos instruções de impressão para mostrar diferentes resultados que serão visíveis na área de depuração na parte inferior do Xcode.
Este tutorial representa uma pequena parte de um curso completo sobre desenvolvimento de BLE para iOS na Bluetooth Developer Academy. O curso foi desenvolvido em parceria com Anas Imtiaz , PhD .
Neste tutorial, examinaremos o desenvolvimento de aplicativos para iPhone / iPad que fazem interface com um periférico Bluetooth Low Energy para enviar / receber dados.
Começaremos analisando o Core Bluetooth , uma estrutura fornecida pela Apple para facilitar o desenvolvimento do BLE por meio do uso de APIs para executar ações diferentes. Também veremos o processo de configuração de um projeto no Xcode para o desenvolvimento do BLE, analisando os estágios de configuração para o uso inicial e levando em consideração o tratamento de permissões para diferentes versões do iOS.
Depois de configurar o fluxo de trabalho, mergulharemos no mundo das principais APIs Bluetooth e codificaremos nosso caminho para desenvolver um aplicativo capaz de:
- Digitalize a área para encontrar os diferentes periféricos BLE
- Exibir informações sobre os periféricos digitalizados
- Conecte-se a um periférico específico
IMPORTANTE : não abordaremos a criação da interface do usuário neste tutorial e focaremos estritamente em começar o desenvolvimento do BLE. Em vez disso, usaremos instruções de impressão para mostrar diferentes resultados que serão visíveis na área de depuração na parte inferior do Xcode.
Pré-requisitos
- Um computador Apple: Macbook, Mac Mini, iMac
- Mac OS
- XCode
- iPhone com BLE (iPhone 4S em diante)
- Periférico BLE (usamos o kit de desenvolvimento nRF52 com exemplo de HRM nórdico)
- Inscrição no Apple Developer Program (gratuito, a menos que você queira implantar na App Store, caso em que custa US $ 99 por ano)
- Compreensão básica de Swift [preferencial, mas não essencial]
Geralmente, a versão mais recente do macOS e XCode é recomendada, mas qualquer coisa a partir de 2015 ou posterior deve estar bem.
Para este tutorial, usaremos:
- MacBook Pro 2017
- macOS Catalina (10.15.2)
- XCode versão 11.3.1
- iPhone 11 (versão iOS 13.3.1)
- Swift 5
- Um computador Apple: Macbook, Mac Mini, iMac
- Mac OS
- XCode
- iPhone com BLE (iPhone 4S em diante)
- Periférico BLE (usamos o kit de desenvolvimento nRF52 com exemplo de HRM nórdico)
- Inscrição no Apple Developer Program (gratuito, a menos que você queira implantar na App Store, caso em que custa US $ 99 por ano)
- Compreensão básica de Swift [preferencial, mas não essencial]
Geralmente, a versão mais recente do macOS e XCode é recomendada, mas qualquer coisa a partir de 2015 ou posterior deve estar bem.
Para este tutorial, usaremos:
- MacBook Pro 2017
- macOS Catalina (10.15.2)
- XCode versão 11.3.1
- iPhone 11 (versão iOS 13.3.1)
- Swift 5
O que é o CoreBluetooth?
O Core Bluetooth é uma estrutura fornecida pela Apple no iOS / iPadOS / macOS para comunicação com todos os dispositivos Bluetooth (BLE ou Classic). Se você tem alguma experiência em programação em dispositivos móveis, particularmente dispositivos Apple, isso parecerá muito familiar, ou seja, uma estrutura que fornece acesso a determinados recursos do sistema através do uso de APIs.
O Core Bluetooth fornece suporte para vários recursos, incluindo:
- Configurando um dispositivo iOS como BLE central ou periférico
- Manipulando parâmetros de conexão de baixo nível
- Estabelecendo e mantendo uma conexão
- Transferindo dados entre dispositivos BLE
- Bluetooth Classic
- Manipulação de erros
Os dois importantes recursos do desenvolvedor da Apple relacionados ao Core Bluetooth que são úteis para entender alguns dos recursos e APIs são:
Núcleo Bluetooth | Documentação do desenvolvedor da Apple
https://developer.apple.com/documentation/corebluetooth
Guia de programação principal do Bluetooth
Observe que existem várias outras bibliotecas por aí que fornecem métodos diferentes para realizar operações BLE no iDevices, no entanto, todas elas são criadas com base no Core Bluetooth, já que essa é a única API que a Apple disponibilizou para os desenvolvedores. Algumas das bibliotecas populares incluem:
- BluetoothKit ( https://github.com/rhummelmose/BluetoothKit )
Fornece funções fáceis de usar para executar tarefas simples
- O RxBluetoothKit ( https://github.com/Polidea/RxBluetoothKit )
usa o Bluetooth principal e o RxSwift
- BlueCap ( https://github.com/troystribling/BlueCap )
Métodos simples para operações assíncronas
Independentemente de qual biblioteca for usada, os conceitos principais permanecerão os mesmos. Com isso em mente, vamos começar!
O Core Bluetooth é uma estrutura fornecida pela Apple no iOS / iPadOS / macOS para comunicação com todos os dispositivos Bluetooth (BLE ou Classic). Se você tem alguma experiência em programação em dispositivos móveis, particularmente dispositivos Apple, isso parecerá muito familiar, ou seja, uma estrutura que fornece acesso a determinados recursos do sistema através do uso de APIs.
O Core Bluetooth fornece suporte para vários recursos, incluindo:
- Configurando um dispositivo iOS como BLE central ou periférico
- Manipulando parâmetros de conexão de baixo nível
- Estabelecendo e mantendo uma conexão
- Transferindo dados entre dispositivos BLE
- Bluetooth Classic
- Manipulação de erros
Os dois importantes recursos do desenvolvedor da Apple relacionados ao Core Bluetooth que são úteis para entender alguns dos recursos e APIs são:
Núcleo Bluetooth | Documentação do desenvolvedor da Apple
https://developer.apple.com/documentation/corebluetooth
Guia de programação principal do Bluetooth
Observe que existem várias outras bibliotecas por aí que fornecem métodos diferentes para realizar operações BLE no iDevices, no entanto, todas elas são criadas com base no Core Bluetooth, já que essa é a única API que a Apple disponibilizou para os desenvolvedores. Algumas das bibliotecas populares incluem:
- BluetoothKit ( https://github.com/rhummelmose/BluetoothKit )
Fornece funções fáceis de usar para executar tarefas simples - O RxBluetoothKit ( https://github.com/Polidea/RxBluetoothKit )
usa o Bluetooth principal e o RxSwift - BlueCap ( https://github.com/troystribling/BlueCap )
Métodos simples para operações assíncronas
Independentemente de qual biblioteca for usada, os conceitos principais permanecerão os mesmos. Com isso em mente, vamos começar!
Configurando um projeto iOS BLE no Xcode
Quando estiver pronto, inicie o XCode e selecione Criar um novo projeto XCode .
Escolha iOS como plataforma na guia na parte superior e, em seguida, selecione Aplicativo de exibição única e pressione Avançar.
Digite o nome do produto . Esse é o nome do nosso aplicativo, então vamos chamá-lo de TheBlueApp .
No menu Equipe , você poderá selecionar seu nome como equipe pessoal se já tiver se inscrito no Apple Developer Program. Se você não vir a opção agora, voltaremos a ela mais tarde e você poderá deixar o padrão por enquanto.
O identificador da organização normalmente é o seu domínio ao contrário. Então você pode usar io.novelbits
.
Na interface do usuário , selecione Storyboard. Estritamente falando, não importa qual método você seleciona, pois isso é aplicável à exibição dos diferentes componentes da interface do usuário. O SwiftUI é relativamente novo e muitos desenvolvedores (inclusive eu) ainda continuam usando o Storyboard, por isso continuaremos assim neste tutorial.
Clique em Avançar, selecione o local no disco rígido em que deseja criar o novo projeto e clique em Criar.
Nosso novo projeto está pronto agora.
Vamos dar uma rápida olhada no que o XCode criou para nós. No lado esquerdo, está o explorador de arquivos, que lista vários arquivos.
Os dois arquivos de preocupação imediata para nós são:
ViewController.swift
Este arquivo contém tudo relacionado à exibição e funcionalidade do nosso aplicativo de exibição única. Info.plist
Esses são os arquivos de configurações e permissões que precisamos usar para ativar o uso do Bluetooth em nosso aplicativo.
Agora, apenas para garantir que nosso iPhone esteja configurado corretamente para implantar o aplicativo, vamos tentar criar esse aplicativo (vazio).
- Conecte seu iPhone via USB ao seu computador de desenvolvimento.
- O telefone pode perguntar se você confia neste computador, permita isso.
- Selecione o telefone no menu superior do XCode, como mostrado abaixo.
- É importante observar que, embora você possa usar o simulador para a maior parte do desenvolvimento de aplicativos, é necessário usar um dispositivo físico para testar a conectividade BLE.
- Clique no botão play na parte superior para criar. Se houver problemas com relação ao seu ID Apple em relação ao programa para desenvolvedores, eles serão relatados aqui e você terá opções para corrigi-los.
- Outra opção é ir para a seção Assinaturas e recursos e selecionar a opção Gerenciar assinatura automaticamente e pressionar o botão para Tentar novamente . Felizmente, isso resolverá quaisquer problemas relacionados à assinatura e certificados.
- Se necessário, construa novamente e aguarde a conclusão do processo. O seu Mac pode solicitar que você digite sua senha. Digite a senha e selecione Sempre permitir .
- Depois que o processo de compilação estiver concluído, o aplicativo será instalado e tentará iniciar.
- Nas versões mais recentes do iOS, você receberá o seguinte erro:
- No iPhone, vá para Configurações → Geral → Gerenciamento de dispositivos . Selecione seu perfil de desenvolvimento e toque em Confiar "Apple Development: <YOUR_APPLE_ID>"
- Inicie o aplicativo novamente e ele deve funcionar, mas como não adicionamos nada ao aplicativo, ele exibirá uma tela em branco.
Até o momento, não desenvolvemos o BLE, mas conseguimos configurar nosso fluxo de trabalho para desenvolver aplicativos no Xcode e implantar no iPhone físico.
Quando estiver pronto, inicie o XCode e selecione Criar um novo projeto XCode .
Escolha iOS como plataforma na guia na parte superior e, em seguida, selecione Aplicativo de exibição única e pressione Avançar.
Digite o nome do produto . Esse é o nome do nosso aplicativo, então vamos chamá-lo de TheBlueApp .
No menu Equipe , você poderá selecionar seu nome como equipe pessoal se já tiver se inscrito no Apple Developer Program. Se você não vir a opção agora, voltaremos a ela mais tarde e você poderá deixar o padrão por enquanto.
O identificador da organização normalmente é o seu domínio ao contrário. Então você pode usar io.novelbits
.
Na interface do usuário , selecione Storyboard. Estritamente falando, não importa qual método você seleciona, pois isso é aplicável à exibição dos diferentes componentes da interface do usuário. O SwiftUI é relativamente novo e muitos desenvolvedores (inclusive eu) ainda continuam usando o Storyboard, por isso continuaremos assim neste tutorial.
Clique em Avançar, selecione o local no disco rígido em que deseja criar o novo projeto e clique em Criar.
Nosso novo projeto está pronto agora.
Vamos dar uma rápida olhada no que o XCode criou para nós. No lado esquerdo, está o explorador de arquivos, que lista vários arquivos.
Os dois arquivos de preocupação imediata para nós são:
ViewController.swift
Este arquivo contém tudo relacionado à exibição e funcionalidade do nosso aplicativo de exibição única.Info.plist
Esses são os arquivos de configurações e permissões que precisamos usar para ativar o uso do Bluetooth em nosso aplicativo.
Agora, apenas para garantir que nosso iPhone esteja configurado corretamente para implantar o aplicativo, vamos tentar criar esse aplicativo (vazio).
- Conecte seu iPhone via USB ao seu computador de desenvolvimento.
- O telefone pode perguntar se você confia neste computador, permita isso.
- Selecione o telefone no menu superior do XCode, como mostrado abaixo.
- É importante observar que, embora você possa usar o simulador para a maior parte do desenvolvimento de aplicativos, é necessário usar um dispositivo físico para testar a conectividade BLE.
- Clique no botão play na parte superior para criar. Se houver problemas com relação ao seu ID Apple em relação ao programa para desenvolvedores, eles serão relatados aqui e você terá opções para corrigi-los.
- Outra opção é ir para a seção Assinaturas e recursos e selecionar a opção Gerenciar assinatura automaticamente e pressionar o botão para Tentar novamente . Felizmente, isso resolverá quaisquer problemas relacionados à assinatura e certificados.
- Se necessário, construa novamente e aguarde a conclusão do processo. O seu Mac pode solicitar que você digite sua senha. Digite a senha e selecione Sempre permitir .
- Depois que o processo de compilação estiver concluído, o aplicativo será instalado e tentará iniciar.
- Nas versões mais recentes do iOS, você receberá o seguinte erro:
- No iPhone, vá para Configurações → Geral → Gerenciamento de dispositivos . Selecione seu perfil de desenvolvimento e toque em Confiar "Apple Development: <YOUR_APPLE_ID>"
- Inicie o aplicativo novamente e ele deve funcionar, mas como não adicionamos nada ao aplicativo, ele exibirá uma tela em branco.
Até o momento, não desenvolvemos o BLE, mas conseguimos configurar nosso fluxo de trabalho para desenvolver aplicativos no Xcode e implantar no iPhone físico.
Importando o CoreBluetooth
Agora, vamos trabalhar na configuração do uso do CoreBluetooth.
O primeiro passo é importar a estrutura CoreBluetooth para o seu projeto. Para fazer isso, adicione a seguinte linha na parte superior do seu ViewController.swift
:
1 import CoreBluetooth
Em seguida, iremos utilizar CBCentralManager
e CBPeripheral
aulas desde o nosso telefone será o gerente central e usaremos métodos para fazer a interface com o dispositivo BLE periférica. Embora tenhamos acesso aos diferentes métodos dessas classes, ainda precisamos estar em conformidade com os métodos delegados definidos pelos protocolos CentralManagerDelegate
e CBPeripheralDelegate
.
Esses são conceitos levemente avançados, mas em termos mais simples, o Swift possui esses padrões de design em que o tempo das chamadas de função é definido, mas seus comportamentos não. Portanto, o comportamento dessas funções deve ser definido. Por exemplo, CBCentralManager
podemos dizer que ele foi conectado a um periférico, mas o que acontece na conexão precisa ser definido por você. Da mesma forma, se houver uma desconexão, o que o objeto do gerente central deve fazer ... ignorar ou tentar restabelecer uma conexão?
Você pode ler mais sobre esse conceito de delegação aqui:
https://www.raywenderlich.com/477-design-patterns-on-ios-using-swift-part-1-2
Para usar esses protocolos, adicione CBCentralManagerDelegate e CBPeripheralDelegate à linha em que sua classe está definida.
12 class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate {...
Assim que você fizer isso, o Xcode começará a reclamar:
Type ‘ViewController’ does not conform to protocol ‘CBCentralManagerDelegate’
Isso ocorre porque alguns dos métodos desses protocolos definitivamente precisam ser definidos, enquanto outros são opcionais.
Se você clicar no círculo vermelho que mostra o erro, a seguir, deve haver um pequeno botão de correção.
Este é o Xcode tentando ajudá-lo e escrever os stubs para os métodos necessários (funções).
Depois de clicar em Corrigir, o contorno da função centralManagerDidUpdateState é exibido:
123 func centralManagerDidUpdateState(_ central: CBCentralManager) { <#code#>}
Remova o esboço "código" por enquanto - preencheremos isso mais tarde.
Este método é um requisito absoluto, pois é chamado sempre que você define a CBCentralManager
. É usado para verificar o status do hardware do Bluetooth no seu dispositivo, ou seja, se está ligado e disponível para uso ou se está desativado. É importante que quaisquer outras operações para conectar-se a um periférico sejam realizadas apenas se o Bluetooth estiver ligado e ativado.
Também queremos declarar uma variável para o nosso dispositivo central, para que possamos consultá-la mais tarde. Dentro da classe, adicione o seguinte:
1 var centralManager: CBCentralManager!
O ponto de exclamação no final significa que se trata de uma variável opcional desembrulhada e, se nos referirmos a ela mais tarde, podemos verificar a segurança nula.
Também queremos declarar uma variável para o nosso objeto periférico assim que estabelecermos uma conexão; portanto, adicione a seguinte linha.
1 var myPeripheral: CBPeripheral!
Na função viewDidLoad (), adicione a seguinte linha para inicializar a centralManager
variável:
1 centralManager = CBCentralManager(delegate: self, queue: nil)
Agora, em ordem de sequência, depois que viewDidLoad () for chamado e nosso centralManager
for inicializado, o método delegado centralManagerDidUpdateState
será chamado. Vejamos como descobrir os diferentes estados de baixa energia do Bluetooth neste método.
Agora, vamos trabalhar na configuração do uso do CoreBluetooth.
O primeiro passo é importar a estrutura CoreBluetooth para o seu projeto. Para fazer isso, adicione a seguinte linha na parte superior do seu ViewController.swift
:
1 | import CoreBluetooth |
Em seguida, iremos utilizar CBCentralManager
e CBPeripheral
aulas desde o nosso telefone será o gerente central e usaremos métodos para fazer a interface com o dispositivo BLE periférica. Embora tenhamos acesso aos diferentes métodos dessas classes, ainda precisamos estar em conformidade com os métodos delegados definidos pelos protocolos CentralManagerDelegate
e CBPeripheralDelegate
.
Esses são conceitos levemente avançados, mas em termos mais simples, o Swift possui esses padrões de design em que o tempo das chamadas de função é definido, mas seus comportamentos não. Portanto, o comportamento dessas funções deve ser definido. Por exemplo, CBCentralManager
podemos dizer que ele foi conectado a um periférico, mas o que acontece na conexão precisa ser definido por você. Da mesma forma, se houver uma desconexão, o que o objeto do gerente central deve fazer ... ignorar ou tentar restabelecer uma conexão?
Você pode ler mais sobre esse conceito de delegação aqui:
https://www.raywenderlich.com/477-design-patterns-on-ios-using-swift-part-1-2
Para usar esses protocolos, adicione CBCentralManagerDelegate e CBPeripheralDelegate à linha em que sua classe está definida.
1 2 | class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate { ... |
Assim que você fizer isso, o Xcode começará a reclamar:
Type ‘ViewController’ does not conform to protocol ‘CBCentralManagerDelegate’
Isso ocorre porque alguns dos métodos desses protocolos definitivamente precisam ser definidos, enquanto outros são opcionais.
Se você clicar no círculo vermelho que mostra o erro, a seguir, deve haver um pequeno botão de correção.
Este é o Xcode tentando ajudá-lo e escrever os stubs para os métodos necessários (funções).
Depois de clicar em Corrigir, o contorno da função centralManagerDidUpdateState é exibido:
1 2 3 | func centralManagerDidUpdateState(_ central: CBCentralManager) { <#code#> } |
Remova o esboço "código" por enquanto - preencheremos isso mais tarde.
Este método é um requisito absoluto, pois é chamado sempre que você define a CBCentralManager
. É usado para verificar o status do hardware do Bluetooth no seu dispositivo, ou seja, se está ligado e disponível para uso ou se está desativado. É importante que quaisquer outras operações para conectar-se a um periférico sejam realizadas apenas se o Bluetooth estiver ligado e ativado.
Também queremos declarar uma variável para o nosso dispositivo central, para que possamos consultá-la mais tarde. Dentro da classe, adicione o seguinte:
1 | var centralManager: CBCentralManager! |
O ponto de exclamação no final significa que se trata de uma variável opcional desembrulhada e, se nos referirmos a ela mais tarde, podemos verificar a segurança nula.
Também queremos declarar uma variável para o nosso objeto periférico assim que estabelecermos uma conexão; portanto, adicione a seguinte linha.
1 | var myPeripheral: CBPeripheral! |
Na função viewDidLoad (), adicione a seguinte linha para inicializar a centralManager
variável:
1 | centralManager = CBCentralManager(delegate: self, queue: nil) |
Agora, em ordem de sequência, depois que viewDidLoad () for chamado e nosso centralManager
for inicializado, o método delegado centralManagerDidUpdateState
será chamado. Vejamos como descobrir os diferentes estados de baixa energia do Bluetooth neste método.
Verificar o status de baixa energia do Bluetooth
Os diferentes estados BLE do dispositivo iOS são do tipo enumerado CBCentralManagerState. Eles são:
123456 CBManagerState.poweredOffCBManagerState.poweredOnCBManagerState.resettingCBManagerState.unauthorizedCBManagerState.unknownCBManagerState.unsupported
Você pode encontrar as definições desses estados aqui:
https://developer.apple.com/documentation/corebluetooth/cbmanagerstate
Os mais importantes a saber são desligados, poweredOn
indicando que o Bluetooth está desativado, indicando que está ligado para que possamos continuar e não suportado, indicando a falta de suporte de hardware para o BLE no dispositivo. Seu aplicativo pode ter alertas diferentes para os diferentes status, mas invariavelmente você precisa ter o estado como ativado para continuar. Para verificar isso, dentro do centralManagerDidUpdateStatus
método, verifique o estado central da seguinte maneira:
12345678910 func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == CBManagerState.poweredOn { print("BLE powered on") // Turned on } else { print("Something wrong with BLE") // Not on, but can have different issues } }
Observe que eu adicionei instruções de impressão para mostrar o status na janela de depuração. Compile esse código e execute no seu dispositivo.
O aplicativo é compilado, mas falha ao iniciar com o seguinte erro:
TheBlueApp [8555: 2463449] [acesso] Este aplicativo falhou porque tentou acessar dados sensíveis à privacidade sem uma descrição de uso. O Info.plist do aplicativo deve conter uma chave NSBluetoothAlwaysUsageDescription com um valor de sequência explicando ao usuário como o aplicativo usa esses dados.
Esta é uma mensagem auto-explicativa sobre a qual a Apple nos alertou na página CoreBluetooth aqui ( https://developer.apple.com/documentation/corebluetooth ):
Os diferentes estados BLE do dispositivo iOS são do tipo enumerado CBCentralManagerState. Eles são:
1 2 3 4 5 6 | CBManagerState.poweredOff CBManagerState.poweredOn CBManagerState.resetting CBManagerState.unauthorized CBManagerState.unknown CBManagerState.unsupported |
Você pode encontrar as definições desses estados aqui:
https://developer.apple.com/documentation/corebluetooth/cbmanagerstate
Os mais importantes a saber são desligados, poweredOn
indicando que o Bluetooth está desativado, indicando que está ligado para que possamos continuar e não suportado, indicando a falta de suporte de hardware para o BLE no dispositivo. Seu aplicativo pode ter alertas diferentes para os diferentes status, mas invariavelmente você precisa ter o estado como ativado para continuar. Para verificar isso, dentro do centralManagerDidUpdateStatus
método, verifique o estado central da seguinte maneira:
1 2 3 4 5 6 7 8 9 10 | func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == CBManagerState.poweredOn { print("BLE powered on") // Turned on } else { print("Something wrong with BLE") // Not on, but can have different issues } } |
Observe que eu adicionei instruções de impressão para mostrar o status na janela de depuração. Compile esse código e execute no seu dispositivo.
O aplicativo é compilado, mas falha ao iniciar com o seguinte erro:
TheBlueApp [8555: 2463449] [acesso] Este aplicativo falhou porque tentou acessar dados sensíveis à privacidade sem uma descrição de uso. O Info.plist do aplicativo deve conter uma chave NSBluetoothAlwaysUsageDescription com um valor de sequência explicando ao usuário como o aplicativo usa esses dados.
Esta é uma mensagem auto-explicativa sobre a qual a Apple nos alertou na página CoreBluetooth aqui ( https://developer.apple.com/documentation/corebluetooth ):
Definindo permissões
Basicamente, o que o erro anterior diz é que precisamos definir um valor para a NSBluetoothAlwaysUsageDescription
chave se estiver usando o iOS13 ou NSBluetoothPeripheralUsageDescription
se estiver usando o iOS12 ou anterior. Essa é a mensagem exibida ao usuário ao solicitar permissão Bluetooth para o aplicativo. Se estivermos projetando aplicativos para serem usados em telefones com iOS13 e versões anteriores, faz sentido definir valores para essas duas chaves. Isso precisa ser feito no arquivo Info.plist .
Vá para o Info.plist
arquivo do explorer à esquerda. Pressione o botão “+” ao lado de Lista de propriedades de informações.
Uma nova linha aparece com um menu suspenso com uma lista de chaves (como texto descritivo).
Selecione Privacidade - Descrição do uso sempre do Bluetooth e digite uma mensagem no campo Valor para esta linha. Algo que informa aos usuários para que o aplicativo usa o Bluetooth. Eu inseri o seguinte.
Este aplicativo usa Bluetooth para receber dados do meu sensor.
Em seguida, pressione o botão “+” novamente para adicionar outra tecla.
Desta vez, selecione Privacidade - Descrição do uso periférico de Bluetooth e digite a mesma mensagem para o valor dessa chave.
Seu arquivo plist ficará assim:
Agora crie e execute o aplicativo novamente clicando no pequeno botão play na barra de ferramentas superior. O telefone exibirá uma notificação solicitando permissão para o TheBlueApp usar o Bluetooth.
Selecione OK quando solicitado no telefone solicitando permissão para usar o Bluetooth.
Se tudo correr bem, sua área de depuração mostrará o texto BLE ativado (nossa declaração de impressão).
Sinta-se livre para experimentar diferentes estados para ver como o telefone responde a diferentes configurações.
Agora, podemos usar nosso dispositivo iOS como gerente central, com todas as configurações e permissões classificadas. Agora é hora de pedir ao nosso gerente central que procure dispositivos para encontrar nosso sensor.
Basicamente, o que o erro anterior diz é que precisamos definir um valor para a NSBluetoothAlwaysUsageDescription
chave se estiver usando o iOS13 ou NSBluetoothPeripheralUsageDescription
se estiver usando o iOS12 ou anterior. Essa é a mensagem exibida ao usuário ao solicitar permissão Bluetooth para o aplicativo. Se estivermos projetando aplicativos para serem usados em telefones com iOS13 e versões anteriores, faz sentido definir valores para essas duas chaves. Isso precisa ser feito no arquivo Info.plist .
Vá para o Info.plist
arquivo do explorer à esquerda. Pressione o botão “+” ao lado de Lista de propriedades de informações.
Uma nova linha aparece com um menu suspenso com uma lista de chaves (como texto descritivo).
Selecione Privacidade - Descrição do uso sempre do Bluetooth e digite uma mensagem no campo Valor para esta linha. Algo que informa aos usuários para que o aplicativo usa o Bluetooth. Eu inseri o seguinte.
Este aplicativo usa Bluetooth para receber dados do meu sensor.
Em seguida, pressione o botão “+” novamente para adicionar outra tecla.
Desta vez, selecione Privacidade - Descrição do uso periférico de Bluetooth e digite a mesma mensagem para o valor dessa chave.
Seu arquivo plist ficará assim:
Agora crie e execute o aplicativo novamente clicando no pequeno botão play na barra de ferramentas superior. O telefone exibirá uma notificação solicitando permissão para o TheBlueApp usar o Bluetooth.
Selecione OK quando solicitado no telefone solicitando permissão para usar o Bluetooth.
Se tudo correr bem, sua área de depuração mostrará o texto BLE ativado (nossa declaração de impressão).
Sinta-se livre para experimentar diferentes estados para ver como o telefone responde a diferentes configurações.
Agora, podemos usar nosso dispositivo iOS como gerente central, com todas as configurações e permissões classificadas. Agora é hora de pedir ao nosso gerente central que procure dispositivos para encontrar nosso sensor.
Digitalizando para um periférico BLE
Se o CBManager
estado estiver ligado, solicitaremos à central que procure dispositivos periféricos com o seguinte:
1 central.scanForPeripherals(withServices: nil, options: nil)
Os withServices
parâmetros e options permitem varredura personalizada com base nos UUIDs de serviço, mas, por enquanto, apenas usaremos nil para fazer uma varredura ampla.
O efeito dessa declaração é que, para cada periférico encontrado pelo iPhone, o CBCentralManagerDelegate
método centralManager(_:didDiscover:advertisementData:rssi:)
é chamado.
Na documentação da Apple sobre o Core Bluetooth, esse método "informa ao delegado que o gerente central descobriu um periférico ao procurar dispositivos".
Para cada periférico, ele fornece informações sobre os dados do anúncio como um dicionário de par de valores-chave e o RSSI.
Em nosso projeto, precisamos definir o comportamento desse método delegado. Vá para o final do método delegado anterior (centralManagerDidUpdate), pressione enter para iniciar uma nova linha e comece a digitar diddiscoverperipheral
. O Xcode listará automaticamente os métodos que correspondem às palavras-chave. Certifique-se de selecionar o didDiscoverPeripheral
método que faz parte do CBCentralManagerDelegate
, como mostrado abaixo.
Clique duas vezes no método e o esboço aparecerá.
Podemos identificar nosso periférico por nome, UUID, ID do fabricante ou basicamente qualquer coisa que faça parte dos dados do anúncio. A maneira mais simples é pesquisar pelo nome, mas essa certamente não é uma maneira segura. Idealmente, devemos verificar o nome, UUID e o ID do fabricante.
Por enquanto, apenas verificaremos o nome de cada um dos dispositivos que nosso gerente central encontrou. Dentro do didDiscover
método delegado, digite o seguinte:
1234 if let pname = peripheral.name { print(pname) }}
A primeira linha verifica se o periférico tem um nome (muitos deles não), para evitar que nosso aplicativo falhe, estamos verificando se há nulidade. Se houver um nome, atribuí-lo-emos a uma constante e imprimiremos o valor.
Crie e execute o projeto, e você verá uma lista de nomes aparecendo na sua área de depuração, dependendo de quantos dispositivos existem.
Eu tenho um kit de desenvolvimento nórdico nRF52832 com o exemplo HRM padrão em execução e posso ver que meu dispositivo está listado como Nordic_HRM. O próximo passo é parar a varredura quando o periférico preferido for encontrado e estabelecer uma conexão com esse periférico.
Se o CBManager
estado estiver ligado, solicitaremos à central que procure dispositivos periféricos com o seguinte:
1 | central.scanForPeripherals(withServices: nil, options: nil) |
Os withServices
parâmetros e options permitem varredura personalizada com base nos UUIDs de serviço, mas, por enquanto, apenas usaremos nil para fazer uma varredura ampla.
O efeito dessa declaração é que, para cada periférico encontrado pelo iPhone, o CBCentralManagerDelegate
método centralManager(_:didDiscover:advertisementData:rssi:)
é chamado.
Na documentação da Apple sobre o Core Bluetooth, esse método "informa ao delegado que o gerente central descobriu um periférico ao procurar dispositivos".
Para cada periférico, ele fornece informações sobre os dados do anúncio como um dicionário de par de valores-chave e o RSSI.
Em nosso projeto, precisamos definir o comportamento desse método delegado. Vá para o final do método delegado anterior (centralManagerDidUpdate), pressione enter para iniciar uma nova linha e comece a digitar diddiscoverperipheral
. O Xcode listará automaticamente os métodos que correspondem às palavras-chave. Certifique-se de selecionar o didDiscoverPeripheral
método que faz parte do CBCentralManagerDelegate
, como mostrado abaixo.
Clique duas vezes no método e o esboço aparecerá.
Podemos identificar nosso periférico por nome, UUID, ID do fabricante ou basicamente qualquer coisa que faça parte dos dados do anúncio. A maneira mais simples é pesquisar pelo nome, mas essa certamente não é uma maneira segura. Idealmente, devemos verificar o nome, UUID e o ID do fabricante.
Por enquanto, apenas verificaremos o nome de cada um dos dispositivos que nosso gerente central encontrou. Dentro do didDiscover
método delegado, digite o seguinte:
1 2 3 4 | if let pname = peripheral.name { print(pname) } } |
A primeira linha verifica se o periférico tem um nome (muitos deles não), para evitar que nosso aplicativo falhe, estamos verificando se há nulidade. Se houver um nome, atribuí-lo-emos a uma constante e imprimiremos o valor.
Crie e execute o projeto, e você verá uma lista de nomes aparecendo na sua área de depuração, dependendo de quantos dispositivos existem.
Eu tenho um kit de desenvolvimento nórdico nRF52832 com o exemplo HRM padrão em execução e posso ver que meu dispositivo está listado como Nordic_HRM. O próximo passo é parar a varredura quando o periférico preferido for encontrado e estabelecer uma conexão com esse periférico.
Estabelecendo uma conexão
Durante a digitalização, assim que encontrarmos nosso periférico, queremos interromper a digitalização e estabelecer uma conexão com o periférico. Ao mesmo tempo, queremos manter uma referência a esse periférico para poder executar ações de leitura / gravação.
Embora a maneira mais fácil de identificar um periférico seja pelo nome, essa não é a melhor maneira de fazê-lo. Você deve verificar outras informações, como ID do fabricante, dados do anúncio e UUIDs de serviço. No entanto, para simplificar, ainda usaremos o nome periférico no exemplo a seguir.
Portanto, atualize o código em que estávamos imprimindo o nome periférico da seguinte maneira.
12345678910 if let pname = peripheral.name { if pname == "Nordic_HRM" { self.centralManager.stopScan() self.myPeripheral = peripheral self.myPeripheral.delegate = self self.centralManager.connect(peripheral, options: nil) }}
Primeiro, estamos verificando se pname é Nordic_HRM
, que é o nome anunciado pelo meu kit de desenvolvimento nórdico. Se for esse o caso, solicitamos ao gerente central que pare de digitalizar, pois encontramos o nosso periférico. Em seguida, atribuímos esse periférico ao myPeripheral
objeto e subsequentemente seu delegado como a classe atual do controlador de exibição. Esta segunda parte é importante porque CBPeripheralDelegate
precisa saber quem é o representante aqui que estará em conformidade com seus métodos. Esquecer-se disso é muitas vezes a causa de horas de dores de cabeça, pois os CBPeripheralDelegate
métodos não são chamados e o desenvolvedor fica se perguntando por que esse é o caso. Por fim, pedimos ao gerente central que se conecte a esse periférico recém-encontrado.
Depois que a conexão é estabelecida, o centralManager(_:didConnect:)
método delegado é chamado. Nesse ponto, solicitamos ao periférico que nos forneça mais informações sobre seus serviços usando a seguinte linha no didConnect
método delegado (como antes, quando você começa a digitar didConnectPeripheral
, o Xcode apresenta as opções para o preenchimento automático).
O método ficará assim:
123 func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { self.myPeripheral.discoverServices(nil)}
Observe que você pode passar os UUIDs de serviço como argumento, se já sabe o que está procurando ou pode verificar isso manualmente mais tarde. (Observe também que, se você estiver procurando por um periférico enquanto o aplicativo estiver em segundo plano, precisará fornecer o serviço UUID. Falamos mais sobre isso no curso completo incluído na Bluetooth Developer Academy ).
Nesse ponto, seu ViewController.swift ficará assim:
12345678910111213141516171819202122232425262728293031323334353637383940414243 import UIKitimport CoreBluetooth class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate { var centralManager: CBCentralManager! var myPeripheral: CBPeripheral! func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == CBManagerState.poweredOn { print("BLE powered on") // Turned on central.scanForPeripherals(withServices: nil, options: nil) } else { print("Something wrong with BLE") // Not on, but can have different issues } } func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { if let pname = peripheral.name { if pname == "Nordic_HRM" { self.centralManager.stopScan() self.myPeripheral = peripheral self.myPeripheral.delegate = self self.centralManager.connect(peripheral, options: nil) } } } func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { self.myPeripheral.discoverServices(nil) } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. centralManager = CBCentralManager(delegate: self, queue: nil) }}
Durante a digitalização, assim que encontrarmos nosso periférico, queremos interromper a digitalização e estabelecer uma conexão com o periférico. Ao mesmo tempo, queremos manter uma referência a esse periférico para poder executar ações de leitura / gravação.
Embora a maneira mais fácil de identificar um periférico seja pelo nome, essa não é a melhor maneira de fazê-lo. Você deve verificar outras informações, como ID do fabricante, dados do anúncio e UUIDs de serviço. No entanto, para simplificar, ainda usaremos o nome periférico no exemplo a seguir.
Portanto, atualize o código em que estávamos imprimindo o nome periférico da seguinte maneira.
1 2 3 4 5 6 7 8 9 10 | if let pname = peripheral.name { if pname == "Nordic_HRM" { self.centralManager.stopScan() self.myPeripheral = peripheral self.myPeripheral.delegate = self self.centralManager.connect(peripheral, options: nil) } } |
Primeiro, estamos verificando se pname é Nordic_HRM
, que é o nome anunciado pelo meu kit de desenvolvimento nórdico. Se for esse o caso, solicitamos ao gerente central que pare de digitalizar, pois encontramos o nosso periférico. Em seguida, atribuímos esse periférico ao myPeripheral
objeto e subsequentemente seu delegado como a classe atual do controlador de exibição. Esta segunda parte é importante porque CBPeripheralDelegate
precisa saber quem é o representante aqui que estará em conformidade com seus métodos. Esquecer-se disso é muitas vezes a causa de horas de dores de cabeça, pois os CBPeripheralDelegate
métodos não são chamados e o desenvolvedor fica se perguntando por que esse é o caso. Por fim, pedimos ao gerente central que se conecte a esse periférico recém-encontrado.
Depois que a conexão é estabelecida, o centralManager(_:didConnect:)
método delegado é chamado. Nesse ponto, solicitamos ao periférico que nos forneça mais informações sobre seus serviços usando a seguinte linha no didConnect
método delegado (como antes, quando você começa a digitar didConnectPeripheral
, o Xcode apresenta as opções para o preenchimento automático).
O método ficará assim:
1 2 3 | func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { self.myPeripheral.discoverServices(nil) } |
Observe que você pode passar os UUIDs de serviço como argumento, se já sabe o que está procurando ou pode verificar isso manualmente mais tarde. (Observe também que, se você estiver procurando por um periférico enquanto o aplicativo estiver em segundo plano, precisará fornecer o serviço UUID. Falamos mais sobre isso no curso completo incluído na Bluetooth Developer Academy ).
Nesse ponto, seu ViewController.swift ficará assim:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | import UIKit import CoreBluetooth class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate { var centralManager: CBCentralManager! var myPeripheral: CBPeripheral! func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == CBManagerState.poweredOn { print("BLE powered on") // Turned on central.scanForPeripherals(withServices: nil, options: nil) } else { print("Something wrong with BLE") // Not on, but can have different issues } } func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { if let pname = peripheral.name { if pname == "Nordic_HRM" { self.centralManager.stopScan() self.myPeripheral = peripheral self.myPeripheral.delegate = self self.centralManager.connect(peripheral, options: nil) } } } func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { self.myPeripheral.discoverServices(nil) } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. centralManager = CBCentralManager(delegate: self, queue: nil) } } |
Sumário
Neste tutorial, tivemos uma visão introdutória da interface de um dispositivo iOS com um periférico BLE. Cobrimos:
- Configurando o Xcode para o desenvolvimento do BLE
- Permissões de Bluetooth
- Digitalizando para periféricos BLE
- Conectando a um periférico BLE
(TRADUÇÃO) Sobre a SMARTCORE
A SmartCore fornece módulos para comunicação wireless, biometria, conectividade, rastreamento e automação.Nosso portifólio inclui
modem 2G/3G/4G/NB-IoT/Cat.M, satelital, módulos WiFi, Bluetooth, GNSS /
GPS, Sigfox, LoRa, leitor de cartão, leitor QR code, mecanismo de
impressão, mini-board PC, antena, pigtail, LCD, bateria, repetidor GPS e
sensores.Mais detalhes em www.smartcore.com.br
Neste tutorial, tivemos uma visão introdutória da interface de um dispositivo iOS com um periférico BLE. Cobrimos:
- Configurando o Xcode para o desenvolvimento do BLE
- Permissões de Bluetooth
- Digitalizando para periféricos BLE
- Conectando a um periférico BLE