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
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
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:
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.
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:
Swift
1
importCoreBluetooth
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:
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:
Swift
1
varcentralManager: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.
Swift
1
varmyPeripheral:CBPeripheral!
Na função viewDidLoad (), adicione a seguinte linha para inicializar a centralManagervariável:
Agora, em ordem de sequência, depois que viewDidLoad () for chamado e nosso centralManagerfor inicializado, o método delegado centralManagerDidUpdateStateserá 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:
Swift
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:
Os mais importantes a saber são desligados, poweredOnindicando 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 centralManagerDidUpdateStatusmétodo, verifique o estado central da seguinte maneira:
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.
Basicamente, o que o erro anterior diz é que precisamos definir um valor para a NSBluetoothAlwaysUsageDescriptionchave se estiver usando o iOS13 ou NSBluetoothPeripheralUsageDescriptionse 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.plistarquivo 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 CBManagerestado estiver ligado, solicitaremos à central que procure dispositivos periféricos com o seguinte:
Os withServicesparâ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 CBCentralManagerDelegatemé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 didDiscoverPeripheralmé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 didDiscovermétodo delegado, digite o seguinte:
Swift
1
2
3
4
ifletpname=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.
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 myPeripheralobjeto e subsequentemente seu delegado como a classe atual do controlador de exibição. Esta segunda parte é importante porque CBPeripheralDelegateprecisa 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 CBPeripheralDelegatemé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 didConnectmétodo delegado (como antes, quando você começa a digitar didConnectPeripheral, o Xcode apresenta as opções para o preenchimento automático).
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: