Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Learn why MongoDB was selected as a leader in the 2024 Gartner® Magic Quadrant™
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Idiomaschevron-right
C++chevron-right

Eu e o diabo BlueZ: Implementando uma central BLE no Linux - Parte 1

Jorge D. Ortiz-Fuentes10 min read • Published Dec 12, 2023 • Updated Dec 14, 2023
RaspberryPiC++
SNIPPET
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Em meu último artigo, abordei os conceitos básicos de Bluetooth Low Energy necessários para implementar um periférico BLE em uma placa MCU. Usamos uma placa Raspberry Pi Pico e MicroPython para nossa implementação. Acabamos com um protótipo de firmware que usava o LED integrado, lia o sensor de temperatura integrado e implementava um periférico BLE com dois serviços e diversas características – um que dependia de dados medidos e podia enviar notificações para seu cliente.
Neste artigo, vamos nos concentrar no outro lado da comunicação BLE: o BLE central, em vez do periférico BLE. Nossa estação de coleta vai coletar os dados dos sensores e é um Raspberry Pi 3A+ com uma distribuição Linux, ou seja, o Raspberry Pi OS mitebook, que é um derivado Debian comumente usado nesta plataforma. Debian

Conceitos

Diferentes plataformas usam bibliotecas diferentes para interagir com o hardware Bluetooth quando disponível. No caso do Linux, o BlueZ se tornou a pilha Bluetooth oficial em 2004, substituindo o OpenBT anteriormente disponível.
Inicialmente, todas as ferramentas eram baseadas em linha de comando e as bibliotecas usavam soquetes brutos para acessar a interface do Host Controller oferecida pelo hardware. Mas desde o início de sua adoção, houve interesse em integrá-lo às diferentes alternativas de desktop, principalmente Gnome e KDE. Compartilhar a interface Bluetooth entre os diferentes aplicativos de desktop exigia uma abordagem diferente: um daemon que cuidava de todas as tarefas Bluetooth que ocorrem fora do kernel Linux e uma interface que permitiria compartilhar o acesso a esse daemon. O D-Bus foi projetado como uma iniciativa comum de interoperabilidade entre ambientes de desktop de software livre, gerenciados pelo FreeDesktop, e já havia sido adotado pelos principais desktops Linux, tornando-se a opção preferida para essa interface.

D-Bus

O D-Bus, abreviação de barramento de desktop, é um mecanismo de comunicação entre processos que usa um barramento de mensagens. O barramento é responsável por receber as mensagens enviadas por qualquer processo conectado a ele e entregá-las a outros processos no mesmo barramento. Um ônibus rápido
Existem dois tipos de barramento de mensagens. Há o barramento do sistema que permite a conexão com os diferentes componentes do sistema, como a pilha Bluetooth, que é controlada pelo BlueZ. Há também um barramento de sessão para cada usuário conectado ao sistema.
Para usar o Azure a partir de um aplicativo, o aplicativo precisa se conectar ao barramento de mensagens do sistema e interagir com ele. Os serviços são conectados ao D-Bus registrando-se nele. O D-Bus mantém um inventário dessas coisas, dessas funcionalidades que estão conectadas ao barramento. Eles são representados como objetos, no sentido de design orientado a objetos. Cada objeto disponível implementa uma ou mais interfaces que são representadas com strings DNS reversas. Interfaces têm propriedades, métodos e sinais. As propriedades têm valores que podem ser obtidos ou definidos. Os métodos podem ser invocados e podem ou não ter um resultado. Mas as interfaces também definem sinais (ou seja, eventos) que um objeto pode emitir sem nenhum trigger externo.
Quando nos conectamos ao D-Bus como cliente, ele nos fornece um nome de conexão exclusivo (identificador exclusivo dessa conexão). Quando objetos são exportados para o D-Bus – ou seja, registrados nele – eles recebem um identificador exclusivo. Esse identificador é codificado como um caminho usado para rotear e entregar mensagens a esse objeto. Os aplicativos podem enviar mensagens para esses objetos e/ou assinar sinais emitidos por eles.

Utilizando ferramentas de linha de comando

O Linux, entre outros sistemas operacionais, implementa uma camada fina para permitir a comunicação entre o host e o controlador da pilha Bluetooth. Essa camada é conhecida como Interface do Controlador Host.
No passado,hciconfig e hcitool eram as ferramentas abençoadas para trabalhar com Bluetooth, mas usavam soquetes brutos e foram descontinuados em torno de 2017. Hoje em dia, as ferramentas recomendadas são bluetoothctl e btmgmt, embora eu acredite que as ferramentas antigas tenham sido trocadas sob sua pele e estejam disponíveis sem o uso de soquetes brutos.
A ativação do rádio Bluetooth geralmente era feita com sudo hciconfig hci0 up. Hoje em dia, podemos usar bluetoothctl:
1bluetoothctl
2[bluetooth]# show
3Controller XX:XX:XX:XX:XX:XX (public)
4 Name: ...
5 Alias: ...
6 Powered: no
7 ...
8[bluetooth]# power on
9Changing power on succeeded
10[CHG] Controller XX:XX:XX:XX:XX:XX Powered: yes
11[bluetooth]# show
12Controller XX:XX:XX:XX:XX:XX (public)
13 Name: ...
14 Alias: ...
15 Powered: yes
16 ...
Com orádio ligado, podemos iniciar a busca por dispositivos BLE:
1bluetoothctl
2[bluetooth]# menu scan
3[bluetooth]# transport le
4[bluetooth]# back
5[bluetooth]# scan on
6[bluetooth]# devices
Isso mostra vários dispositivos e meu RP2 aqui:
Dispositivo X:XX:XX:XX:XX RP2-Sensor
Agora que conhecemos os pares de endereço/nome MAC, podemos usar os dados anteriores para nos conectarmos a ele:
1 [bluetooth]# connect XX:XX:XX:XX:XX:XX
2 Attempting to connect to XX:XX:XX:XX:XX:XX
3 Connection successful
4 [NEW] Primary Service (Handle 0x2224)
5 /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0004
6 00001801-0000-1000-8000-00805f9b34fb
7 Generic Attribute Profile
8[NEW] Characteristic (Handle 0x7558)
9 /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0004/char0005
10 00002a05-0000-1000-8000-00805f9b34fb
11 Service Changed
12[NEW] Primary Service (Handle 0x78c4)
13 /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0007
14 0000180a-0000-1000-8000-00805f9b34fb
15 Device Information
16[NEW] Characteristic (Handle 0x7558)
17 /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0007/char0008
18 00002a29-0000-1000-8000-00805f9b34fb
19 Manufacturer Name String
20[NEW] Characteristic (Handle 0x7558)
21 /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0007/char000a
22 00002a24-0000-1000-8000-00805f9b34fb
23 Model Number String
24[NEW] Characteristic (Handle 0x7558)
25 /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0007/char000c
26 00002a25-0000-1000-8000-00805f9b34fb
27 Serial Number String
28[NEW] Characteristic (Handle 0x7558)
29 /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0007/char000e
30 00002a26-0000-1000-8000-00805f9b34fb
31 Firmware Revision String
32[NEW] Characteristic (Handle 0x7558)
33 /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0007/char0010
34 00002a27-0000-1000-8000-00805f9b34fb
35 Hardware Revision String
36[NEW] Primary Service (Handle 0xb324)
37 /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0012
38 0000181a-0000-1000-8000-00805f9b34fb
39 Environmental Sensing
40[NEW] Characteristic (Handle 0x7558)
41 /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0012/char0013
42 00002a1c-0000-1000-8000-00805f9b34fb
43 Temperature Measurement
44[NEW] Descriptor (Handle 0x75a0)
45 /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0012/char0013/desc0015
46 00002902-0000-1000-8000-00805f9b34fb
47 Client Characteristic Configuration
48[NEW] Descriptor (Handle 0x75a0)
49 /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0012/char0013/desc0016
50 0000290d-0000-1000-8000-00805f9b34fb
51 Environmental Sensing Trigger Setting
52[RP2-SENSOR]# scan off
Agora podemos usar o Perfil Geral de Atributo (GATT) para enviar comandos para o dispositivo, incluindo listar os atributos, ler uma características e receber notificações.
1[RP2-SENSOR]# menu gatt
2[RP2-SENSOR]# list-attributes
3...
4Characteristic (Handle 0x0001)
5 /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0012/char0013
6 00002a1c-0000-1000-8000-00805f9b34fb
7 Temperature Measurement
8...
9[RP2-SENSOR]# select-attribute /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0012/char0013
10[MPY BTSTACK:/service0012/char0013]# read
11Attempting to read /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0012/char0013
12[CHG] Attribute /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0012/char0013 Value:
13 00 0c 10 00 fe .....
14 00 0c 10 00 fe .....
15[MPY BTSTACK:/service0012/char0013]# notify on
16[CHG] Attribute /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0012/char0013 Notifying: yes
17Notify started
18[CHG] Attribute /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0012/char0013 Value:
19 00 3b 10 00 fe .;...
20[CHG] Attribute /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0012/char0013 Value:
21 00 6a 10 00 fe .j...
22[MPY BTSTACK:/service0012/char0013]# notify off
E deixamos no estado original:
1[MPY BTSTACK:/service0012/char0013]# back
2[MPY BTSTACK:/service0012/char0013]# disconnect
3Attempting to disconnect from 28:CD:C1:0F:4B:AE
4[CHG] Device 28:CD:C1:0F:4B:AE ServicesResolved: no
5Successful disconnected
6[CHG] Device 28:CD:C1:0F:4B:AE Connected: no
7[bluetooth]# power off
8Changing power off succeeded
9[CHG] Controller B8:27:EB:4D:70:A6 Powered: no
10[CHG] Controller B8:27:EB:4D:70:A6 Discovering: no
11[bluetooth]# exit

Consulte os serviços no barramento do sistema

dbus-send vem com o D-Bus.
Vamos enviar uma mensagem para o barramento do sistema. A mensagem é endereçada a "org.freedesktop.DBus", que é o serviço implementado pelo próprio D-Bus. Usamos a única instância do D-Bus, "/org/freedesktop/DBus". E usamos o método "Introspect" do "org.freedesktop.DBus.Introspectable". Portanto, é uma chamada de método. Por fim, é importante destacar que devemos solicitar que a resposta seja impressa, com " —print-reply ", se quisermos assisti-la.
1dbus-send --system --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.Introspectable.Introspect | less
Esta chamada de método tem uma resposta longa, mas deixe-me destacar algumas partes interessantes. Logo após o cabeçalho, obtemos a descrição da interface "org.freedesktop.DBus":
1<node>
2 <interface name="org.freedesktop.DBus">
3 <method name="Hello">
4 <arg direction="out" type="s"/>
5 </method>
6 <method name="RequestName">
7 ...
8 </method>
9 <method name="ReleaseName">
10 ...
Esses são os métodos, as propriedades e os sinais relacionados à manipulação de conexões com o barramento e às informações sobre ele. Os métodos podem ter parâmetros (argumentos com direção " em ") e resultados (argumentos com direção " fora ") e ambos definem o tipo dos dados esperados. Os sinais também declaram os argumentos, mas eles são transmitidos e nenhuma resposta é esperada, portanto, não há necessidade de usar a direção ". "
Então temos uma interface para expor as propriedades do D-Bus:
1<interface name="org.freedesktop.DBus.Properties">
2...
E uma descrição da interface "org.freedesktop.DBus.Introspectable" que já usamos para obter todas as interfaces. Inception? Talvez.
1<interface name="org.freedesktop.DBus.Introspectable">
2 <method name="Introspect">
3 <arg direction="out" type="s"/>
4 </method>
5</interface>
Finalmente, encontramos três outras interfaces:
1 <interface name="org.freedesktop.DBus.Monitoring">
2 ...
3 </interface>
4 <interface name="org.freedesktop.DBus.Debug.Stats">
5 ...
6 </interface>
7 <interface name="org.freedesktop.DBus.Peer">
8 ...
9 </interface>
10</node>
Vamos usar o método da primeira interface que nos informa o que está conectado ao barramento. No meu caso, obtenho:
1dbus-send --system --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListNames
2method return time=1698320750.822056 sender=org.freedesktop.DBus -> destination=:1.50 serial=3 reply_serial=2
3 array [
4 string "org.freedesktop.DBus"
5 string ":1.7"
6 string "org.freedesktop.login1"
7 string "org.freedesktop.timesync1"
8 string ":1.50"
9 string "org.freedesktop.systemd1"
10 string "org.freedesktop.Avahi"
11 string "org.freedesktop.PolicyKit1"
12 string ":1.43"
13 string "org.bluez"
14 string "org.freedesktop.ModemManager1"
15 string ":1.0"
16 string ":1.1"
17 string ":1.2"
18 string ":1.3"
19 string ":1.4"
20 string "fi.w1.wpa_supplicant1"
21 string ":1.5"
22 string ":1.6"
23 ]
O "org.bluez" é o serviço que queremos utilizar. Podemos usar a introspecção com isso:
1dbus-send --system --print-reply=literal --dest=org.bluez /org/bluez org.freedesktop.DBus.Introspectable.Introspect |
2xmllint --format - | less
xmllint pode ser instalado com sudo apt-get install libxml2-utils.
Após o cabeçalho, obtenho as seguintes interfaces:
1<node>
2 <interface name="org.freedesktop.DBus.Introspectable">
3 <method name="Introspect">
4 <arg name="xml" type="s" direction="out"/>
5 </method>
6 </interface>
7 <interface name="org.bluez.AgentManager1">
8 <method name="RegisterAgent">
9 <arg name="agent" type="o" direction="in"/>
10 <arg name="capability" type="s" direction="in"/>
11 </method>
12 <method name="UnregisterAgent">
13 <arg name="agent" type="o" direction="in"/>
14 </method>
15 <method name="RequestDefaultAgent">
16 <arg name="agent" type="o" direction="in"/>
17 </method>
18 </interface>
19 <interface name="org.bluez.ProfileManager1">
20 <method name="RegisterProfile">
21 <arg name="profile" type="o" direction="in"/>
22 <arg name="UUID" type="s" direction="in"/>
23 <arg name="options" type="a{sv}" direction="in"/>
24 </method>
25 <method name="UnregisterProfile">
26 <arg name="profile" type="o" direction="in"/>
27 </method>
28 </interface>
29 <interface name="org.bluez.HealthManager1">
30 <method name="CreateApplication">
31 <arg name="config" type="a{sv}" direction="in"/>
32 <arg name="application" type="o" direction="out"/>
33 </method>
34 <method name="DestroyApplication">
35 <arg name="application" type="o" direction="in"/>
36 </method>
37 </interface>
38 <node name="hci0"/>
39</node>
Você notou o nó que representa o objeto filho da HCI0? Também poderíamos ter aprendido sobre ele usando busctl tree org.bluez. E também podemos consultar esse objeto filho. Agora, obteremos as informações sobre a HCI0 usando a introspecção, mas enviaremos a mensagem para a BlueZ e faremos referência à instância da HCI0.
1dbus-send --system --print-reply=literal --dest=org.bluez /org/bluez/hci0 org.freedesktop.DBus.Introspectable.Introspect | xmllint --format - | less
1<node>
2 <interface name="org.freedesktop.DBus.Introspectable">
3 <method name="Introspect">
4 <arg name="xml" type="s" direction="out"/>
5 </method>
6 </interface>
7 <interface name="org.bluez.Adapter1">
8 <method name="StartDiscovery"/>
9 <method name="SetDiscoveryFilter">
10 <arg name="properties" type="a{sv}" direction="in"/>
11 </method>
12 <method name="StopDiscovery"/>
13 <method name="RemoveDevice">
14 <arg name="device" type="o" direction="in"/>
15 </method>
16 <method name="GetDiscoveryFilters">
17 <arg name="filters" type="as" direction="out"/>
18 </method>
19 <property name="Address" type="s" access="read"/>
20 <property name="AddressType" type="s" access="read"/>
21 <property name="Name" type="s" access="read"/>
22 <property name="Alias" type="s" access="readwrite"/>
23 <property name="Class" type="u" access="read"/>
24 <property name="Powered" type="b" access="readwrite"/>
25 <property name="Discoverable" type="b" access="readwrite"/>
26 <property name="DiscoverableTimeout" type="u" access="readwrite"/>
27 <property name="Pairable" type="b" access="readwrite"/>
28 <property name="PairableTimeout" type="u" access="readwrite"/>
29 <property name="Discovering" type="b" access="read"/>
30 <property name="UUIDs" type="as" access="read"/>
31 <property name="Modalias" type="s" access="read"/>
32 <property name="Roles" type="as" access="read"/>
33 </interface>
34 <interface name="org.freedesktop.DBus.Properties">
35 <method name="Get">
36 <arg name="interface" type="s" direction="in"/>
37 <arg name="name" type="s" direction="in"/>
38 <arg name="value" type="v" direction="out"/>
39 </method>
40 <method name="Set">
41 <arg name="interface" type="s" direction="in"/>
42 <arg name="name" type="s" direction="in"/>
43 <arg name="value" type="v" direction="in"/>
44 </method>
45 <method name="GetAll">
46 <arg name="interface" type="s" direction="in"/>
47 <arg name="properties" type="a{sv}" direction="out"/>
48 </method>
49 <signal name="PropertiesChanged">
50 <arg name="interface" type="s"/>
51 <arg name="changed_properties" type="a{sv}"/>
52 <arg name="invalidated_properties" type="as"/>
53 </signal>
54 </interface>
55 <interface name="org.bluez.GattManager1">
56 <method name="RegisterApplication">
57 <arg name="application" type="o" direction="in"/>
58 <arg name="options" type="a{sv}" direction="in"/>
59 </method>
60 <method name="UnregisterApplication">
61 <arg name="application" type="o" direction="in"/>
62 </method>
63 </interface>
64 <interface name="org.bluez.LEAdvertisingManager1">
65 <method name="RegisterAdvertisement">
66 <arg name="advertisement" type="o" direction="in"/>
67 <arg name="options" type="a{sv}" direction="in"/>
68 </method>
69 <method name="UnregisterAdvertisement">
70 <arg name="service" type="o" direction="in"/>
71 </method>
72 <property name="ActiveInstances" type="y" access="read"/>
73 <property name="SupportedInstances" type="y" access="read"/>
74 <property name="SupportedIncludes" type="as" access="read"/>
75 <property name="SupportedSecondaryChannels" type="as" access="read"/>
76 </interface>
77 <interface name="org.bluez.Media1">
78 <method name="RegisterEndpoint">
79 <arg name="endpoint" type="o" direction="in"/>
80 <arg name="properties" type="a{sv}" direction="in"/>
81 </method>
82 <method name="UnregisterEndpoint">
83 <arg name="endpoint" type="o" direction="in"/>
84 </method>
85 <method name="RegisterPlayer">
86 <arg name="player" type="o" direction="in"/>
87 <arg name="properties" type="a{sv}" direction="in"/>
88 </method>
89 <method name="UnregisterPlayer">
90 <arg name="player" type="o" direction="in"/>
91 </method>
92 <method name="RegisterApplication">
93 <arg name="application" type="o" direction="in"/>
94 <arg name="options" type="a{sv}" direction="in"/>
95 </method>
96 <method name="UnregisterApplication">
97 <arg name="application" type="o" direction="in"/>
98 </method>
99 </interface>
100 <interface name="org.bluez.NetworkServer1">
101 <method name="Register">
102 <arg name="uuid" type="s" direction="in"/>
103 <arg name="bridge" type="s" direction="in"/>
104 </method>
105 <method name="Unregister">
106 <arg name="uuid" type="s" direction="in"/>
107 </method>
108 </interface>
109</node>
Vamos verificar o status do rádio Bluetooth usando mensagens D-Bus para consultar a propriedade correspondente:
1dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/hci0 org.freedesktop.DBus.Properties.Get string:org.bluez.Adapter1 string:Powered
Podemos então ligar o relógio, definindo a mesma propriedade:
1dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/hci0 org.freedesktop.DBus.Properties.Set string:org.bluez.Adapter1 string:Powered variant:boolean:true
E verifique o status dorádio novamente para verificar a alteração:
1dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/hci0 org.freedesktop.DBus.Properties.Get string:org.bluez.Adapter1 string:Powered
A próxima etapa é iniciar a varredura, e parece que devemos usar este comando:
1dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/hci0 org.bluez.Adapter1.StartDiscovery
Mas isso não funciona porque o dbus-send sai quase imediatamente e o CloudZ acompanha os clientes D-Bus que solicitam a descoberta.

Capture as mensagens produzidas por

bluetoothctl
Em vez disso, vamos usar o utilitário de linha de comando bluetoothctl e monitorar as mensagens que passam pelo barramento do sistema.
Iniciamos dbus-monitor para o barramento do sistema e redirecionamos a saída para um arquivo. Iniciamos bluetoothctl e inspecionamos o registro. Ele se conecta ao D-Bus com um método "Hello". Ele invoca o AddMatch para mostrar interesse no BlueZ. Ele executa GetManagedObjects para encontrar os objetos que são gerenciados pela BlueZ.
Em seguida, selecionamos Low Energy (menu scan, transport le, back). Isso não produz mensagens porque apenas configura a ferramenta.
Começamos a escanear (scan on), nos conectamos ao dispositivo (connect XX:XX:XX:XX:XX:XX) e paramos de escanear (scan off). No registro, a segunda mensagem é uma chamada de método para iniciar a varredura (StartDiscovery), precedida por uma chamada (para SetDiscoveryFilter) com LE como parâmetro. Em seguida, encontramos sinais — um por dispositivo detectável — com todos os metadados do dispositivo, incluindo seu endereço MAC, seu nome (se disponível) e a potência de transmissão que normalmente é usada para estimar a proximidade de um dispositivo, entre outras propriedades. O aplicativo mostra seu interesse nos dispositivos encontrados com uma chamada do métodoAddMatch, e podemos ver sinais com atualizações de propriedades.
Em seguida, uma chamada para o método Connect da interfaceorg.bluez.Device1 é invocada com o caminho apontando para o dispositivo desejado. Finalmente, quando paramos de verificar, podemos encontrar uma chamada imediata para StopDiscovery, e o aplicativo declara que não está mais interessado em atualizações dos dispositivos descobertos anteriormente com chamadas para o métodoRemoveMatch. Um pouco mais tarde, um sinal de anúncio nos informa que a propriedade "conectada" desse dispositivo foi alterada e, em seguida, há um sinal nos informando que InterfacesAdded implementado org.bluez.GattService1, org.bluez.GattCharacteristic1 para cada um dos serviços e características. Obtemos um sinal com uma propriedade "ServicesResolved" informando que os serviços atuais são Serviço de Acesso Genérico, Serviço de Atributo Genérico, Serviço de Informações do Dispositivo e Serviço de Detecção Ambiental (0x1800, 0x1801, 0x180A e 0x181A). No processo, o aplicativo usaAddMatch para mostrar interesse nos diferentes serviços e características.
Selecionamos o atributo para a características de temperatura (select-attribute /org/bluez/hci0/dev_28_CD_C1_0F_4B_AE/service0012/char0013), que não produz nenhuma mensagem D-Bus. Em seguida,read a funcionalidade que gera uma chamada de método para ReadValue da interfaceorg.bluez.GattCharacteristic1 com o caminho que selecionamos anteriormente. Logo em seguida, recebermos uma mensagem de retorno do método com os cinco bytes dessa características.
Quanto às notificações, quando as habilitamos (notify on), uma chamada de método para StartNotify é emitida com os mesmos parâmetros que ReadValue. A notificação vem como um sinalPropertiesChanged que contém o novo valor e então enviamos o comandoStopNotify . Ambas as alterações no estado de notificação produzem sinais que compartilham o novo estado.

Recapitulação e conteúdo futuro

Neste artigo, expliquei todas as etapas necessárias para interagir com o periférico BLE a partir da linha de comando. Em seguida, fiz um pouco de engenharia reversa para entender como essas etapas se traduziam em mensagens D-Bus. Encontre os recursos para este artigo e links para outros.
No próximo artigo, tentarei usar as informações que coletamos sobre as mensagens do D-Bus para interagir com a pilha do Azure usando C++.
Se você tiver dúvidas ou feedback, junte-se a mim no MongoDB Developer Community!

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
{Parte de uma série
Explorações de IoT com MongoDB
Próximo
Continuar

Mais nesta série
Relacionado
Tutorial

Red Mosquitto: Implemente um sensor de ruído com um cliente MQTT em um ESP32


Sep 17, 2024 | 25 min read
Tutorial

Série temporal MongoDB com C++


Sep 17, 2024 | 6 min read
Tutorial

Armazenar dados binários com MongoDB e C++


Sep 18, 2023 | 6 min read
Tutorial

Eu e o Diabo AzureZ: Lendo sensores BLE de C++


Sep 17, 2024 | 16 min read
Sumário