bluetooth — Bluetooth de baixo nível¶
Este módulo fornece uma interface para o controlador Bluetooth integrado. Suporta Bluetooth Low Energy (BLE) nos papéis de Central, Periférico, Transmissor e Observador, bem como servidor e cliente GATT e canais orientados a ligação L2CAP. Um dispositivo pode operar em vários papéis em simultâneo. O emparelhamento e a vinculação também são suportados.
Esta API destina-se a corresponder ao protocolo Bluetooth de baixo nível e a fornecer blocos construtivos para abstrações de nível mais elevado, como tipos de dispositivos específicos.
Dica
Para a maioria das aplicações, prefira a biblioteca de nível mais elevado aioble, que fornece um wrapper baseado em asyncio em torno deste módulo. Consulte aioble — BLE Assíncrono.
class BLE¶
- class bluetooth.BLE¶
Devolve o objeto BLE singleton.
Configuração
- active(active: bool | None = None, /) bool¶
Opcionalmente altera o estado ativo do rádio BLE e devolve o estado atual.
O rádio deve ser ativado antes de utilizar qualquer outro método desta classe.
- config(param: str, /) Any¶
- config(*, **kwargs: Any) None
Obtém ou define valores de configuração da interface BLE. Para obter um valor, o nome do parâmetro deve ser indicado como uma string, e apenas um parâmetro é consultado de cada vez. Para definir valores, utilize a sintaxe de palavra-chave, podendo ser definidos um ou mais parâmetros de cada vez.
Os valores atualmente suportados são:
'mac': O endereço atual em uso, dependendo do modo de endereço atual. Devolve um tuplo de(addr_type, addr).Consulte
gap_scanpara detalhes sobre o tipo de endereço.Isto só pode ser consultado enquanto a interface estiver ativa.
'addr_mode': Define o modo de endereço. Os valores são:Valor
Nome
Comportamento
0x00PUBLIC
Utiliza o endereço público do controlador.
0x01RANDOM
Utiliza um endereço estático gerado.
0x02RPA
Utiliza endereços privados resolúveis.
0x03NRPA
Utiliza endereços privados não resolúveis.
Por defeito, a interface utilizará um endereço PUBLIC se disponível; caso contrário, utilizará um endereço RANDOM.
'gap_name': Obtém/define o nome do dispositivo GAP utilizado pelo serviço de Acesso Genérico (UUID0x1800), característica Nome do Dispositivo (UUID0x2a00). Pode ser definido em qualquer momento e alterado várias vezes.'rxbuf': Obtém/define o tamanho em bytes do buffer interno utilizado para armazenar eventos recebidos. Este buffer é global para todo o controlador BLE e trata, portanto, os dados recebidos para todos os eventos, incluindo todas as características. Aumentar este valor permite um melhor tratamento de dados recebidos em rajada (por exemplo, resultados de pesquisa) e a capacidade de receber valores de características maiores.'mtu': Obtém/define o MTU que será utilizado durante uma troca de MTU ATT. O MTU resultante será o mínimo entre este e o MTU do dispositivo remoto. A troca de MTU ATT não ocorre automaticamente (a menos que o dispositivo remoto a inicie) e deve ser iniciada manualmente comgattc_exchange_mtu. Utilize o evento_IRQ_MTU_EXCHANGEDpara descobrir o MTU de uma ligação específica.'bond': Define se a vinculação será ativada durante o emparelhamento. Quando ativada, os pedidos de emparelhamento definirão o sinalizador «bond» e as chaves serão armazenadas por ambos os dispositivos.'mitm': Define se a proteção MITM é necessária para o emparelhamento.'io': Define as capacidades de I/O deste dispositivo.As opções disponíveis são:
Constante
Valor
Capacidade
_IO_CAPABILITY_DISPLAY_ONLY0
Apenas visualização
_IO_CAPABILITY_DISPLAY_YESNO1
Visualização com entrada sim/não
_IO_CAPABILITY_KEYBOARD_ONLY2
Apenas teclado
_IO_CAPABILITY_NO_INPUT_OUTPUT3
Sem entrada nem saída
_IO_CAPABILITY_KEYBOARD_DISPLAY4
Teclado e visualização
'le_secure': Define se o emparelhamento «LE Secure» é obrigatório. O valor por defeito é falso (ou seja, permite «Legacy Pairing»).
Tratamento de Eventos
- irq(handler: Callable[[int, Tuple], Any | None], /) None¶
Regista um callback para eventos do stack BLE. O handler recebe dois argumentos:
event(que será um dos códigos abaixo) edata(que é um tuplo de valores específicos do evento).Nota: Como otimização para evitar alocações desnecessárias, as entradas
addr,adv_data,char_data,notify_dataeuuidnos tuplos são instâncias de memoryview somente de leitura que apontam para o ringbuffer interno dobluetooth, sendo válidas apenas durante a invocação da função de tratamento de IRQ. Se o seu programa precisar de guardar um destes valores para acesso após o retorno do tratador de IRQ (por exemplo, guardando-o numa instância de classe ou numa variável global), é necessário fazer uma cópia dos dados, utilizandobytes()oubluetooth.UUID(), da seguinte forma:connected_addr = bytes(addr) # equivalently: adv_data, char_data, or notify_data matched_uuid = bluetooth.UUID(uuid)
Por exemplo, o tratador de IRQ para um resultado de pesquisa pode inspecionar
adv_datapara decidir se é o dispositivo correto, copiando apenas depois os dados do endereço para utilização noutro ponto do programa. Para imprimir dados dentro do tratador de IRQ, será necessárioprint(bytes(addr)).Um tratador tipicamente despacha com base no código do evento e desempacota o tuplo de payload específico do evento:
def bt_irq(event, data): if event == _IRQ_CENTRAL_CONNECT: conn_handle, addr_type, addr = data ... elif event == _IRQ_SCAN_RESULT: addr_type, addr, adv_type, rssi, adv_data = data ...
Todos os códigos de evento, o payload que entregam e uma breve descrição são listados abaixo. Para eventos cujo campo
statusé mencionado,statusé0em caso de sucesso e um valor não nulo específico da implementação em caso de falha.Constante
Valor
Evento
Tuplo de payload
_IRQ_CENTRAL_CONNECT1
Um central ligou-se a este periférico.
(conn_handle, addr_type, addr)_IRQ_CENTRAL_DISCONNECT2
Um central desligou-se deste periférico.
(conn_handle, addr_type, addr)_IRQ_GATTS_WRITE3
Um cliente ligado escreveu numa característica ou descritor local. Utilize
gatts_readpara obter o novo valor.(conn_handle, attr_handle)_IRQ_GATTS_READ_REQUEST4
Um cliente ligado emitiu uma leitura. Devolva um código de erro não nulo da tabela abaixo para recusar a leitura, ou
0/Nonepara a aceitar.(conn_handle, attr_handle)_IRQ_SCAN_RESULT5
Um pacote de publicidade único foi recebido durante uma pesquisa ativa.
(addr_type, addr, adv_type, rssi, adv_data)_IRQ_SCAN_DONE6
A pesquisa atual terminou, seja porque a duração configurada expirou ou porque
gap_scan(None)foi chamado.()_IRQ_PERIPHERAL_CONNECT7
Um
gap_connectemitido anteriormente teve sucesso.(conn_handle, addr_type, addr)_IRQ_PERIPHERAL_DISCONNECT8
Um periférico ligado desligou-se.
(conn_handle, addr_type, addr)_IRQ_GATTC_SERVICE_RESULT9
Um serviço foi encontrado por
gattc_discover_services.(conn_handle, start_handle, end_handle, uuid)_IRQ_GATTC_SERVICE_DONE10
A descoberta de serviços terminou.
(conn_handle, status)_IRQ_GATTC_CHARACTERISTIC_RESULT11
Uma característica foi encontrada por
gattc_discover_characteristics.(conn_handle, end_handle, value_handle, properties, uuid)_IRQ_GATTC_CHARACTERISTIC_DONE12
A descoberta de características terminou.
(conn_handle, status)_IRQ_GATTC_DESCRIPTOR_RESULT13
Um descritor foi encontrado por
gattc_discover_descriptors.(conn_handle, dsc_handle, uuid)_IRQ_GATTC_DESCRIPTOR_DONE14
A descoberta de descritores terminou.
(conn_handle, status)_IRQ_GATTC_READ_RESULT15
Um
gattc_reademitido anteriormente devolveu dados.(conn_handle, value_handle, char_data)_IRQ_GATTC_READ_DONE16
Um
gattc_reademitido anteriormente terminou.(conn_handle, value_handle, status)_IRQ_GATTC_WRITE_DONE17
Um
gattc_writeemitido anteriormente foi reconhecido.(conn_handle, value_handle, status)_IRQ_GATTC_NOTIFY18
Um servidor remoto enviou uma notificação (não reconhecida).
(conn_handle, value_handle, notify_data)_IRQ_GATTC_INDICATE19
Um servidor remoto enviou uma indicação (reconhecida).
(conn_handle, value_handle, notify_data)_IRQ_GATTS_INDICATE_DONE20
Uma indicação enviada anteriormente foi reconhecida pelo cliente (ou expirou o tempo limite).
(conn_handle, value_handle, status)_IRQ_MTU_EXCHANGED21
Uma troca de MTU ATT foi concluída (iniciada por qualquer lado).
(conn_handle, mtu)_IRQ_L2CAP_ACCEPT22
Um dispositivo remoto solicitou uma ligação L2CAP num PSM em que este dispositivo está à escuta. Devolva um inteiro não nulo para recusar, ou
0/Nonepara aceitar.(conn_handle, cid, psm, our_mtu, peer_mtu)_IRQ_L2CAP_CONNECT23
Um canal L2CAP está agora estabelecido, seja por aceitação de um pedido de entrada ou por conclusão de um
l2cap_connectde saída.(conn_handle, cid, psm, our_mtu, peer_mtu)_IRQ_L2CAP_DISCONNECT24
Um canal L2CAP foi desligado.
statusé0para um desligamento limpo, ou não nulo se uma tentativa de ligação de saída falhou.(conn_handle, cid, psm, status)_IRQ_L2CAP_RECV25
Chegaram dados num canal L2CAP. Chame
l2cap_recvintopara os ler.(conn_handle, cid)_IRQ_L2CAP_SEND_READY26
Um
l2cap_sendanterior que devolveuFalsefoi drenado e o canal está pronto novamente. Umstatusnão nulo significa que o buffer de transmissão transbordou e a aplicação tem de reenviar os dados.(conn_handle, cid, status)_IRQ_CONNECTION_UPDATE27
O dispositivo remoto atualizou os parâmetros de ligação (intervalo, latência, timeout de supervisão).
(conn_handle, conn_interval, conn_latency, supervision_timeout, status)_IRQ_ENCRYPTION_UPDATE28
O estado de encriptação de uma ligação mudou, tipicamente após a conclusão do emparelhamento ou vinculação.
(conn_handle, encrypted, authenticated, bonded, key_size)_IRQ_GET_SECRET29
O stack está a solicitar um segredo de vinculação armazenado. Se
keyforNone, devolve oindexº valor armazenado desec_type; caso contrário, devolve o valor associado ao par(sec_type, key)fornecido. DevolveNonese nada estiver armazenado.(sec_type, index, key)_IRQ_SET_SECRET30
O stack está a pedir à aplicação para persistir um segredo de vinculação. Devolva
Trueapós o armazenamento.(sec_type, key, value)_IRQ_PASSKEY_ACTION31
É necessária uma ação de passkey como parte do emparelhamento. Responda utilizando
gap_passkey; consulte a tabela de ações de passkey abaixo para as ações possíveis.(conn_handle, action, passkey)Para o evento
_IRQ_GATTS_READ_REQUEST, os códigos de retorno disponíveis são:Constante
Valor
Significado
_GATTS_NO_ERROR0x00Aceitar a leitura.
_GATTS_ERROR_READ_NOT_PERMITTED0x02Leitura não permitida.
_GATTS_ERROR_WRITE_NOT_PERMITTED0x03Escrita não permitida.
_GATTS_ERROR_INSUFFICIENT_AUTHENTICATION0x05O cliente não está autenticado.
_GATTS_ERROR_INSUFFICIENT_AUTHORIZATION0x08O cliente não está autorizado.
_GATTS_ERROR_INSUFFICIENT_ENCRYPTION0x0fA ligação não está encriptada.
Para o evento
_IRQ_PASSKEY_ACTION, as ações disponíveis são:Constante
Valor
Significado
_PASSKEY_ACTION_NONE0
Nenhuma ação necessária.
_PASSKEY_ACTION_INPUT2
Pedir ao utilizador para introduzir o passkey mostrado no dispositivo remoto.
_PASSKEY_ACTION_DISPLAY3
Mostrar um passkey de 6 dígitos para o dispositivo remoto introduzir.
_PASSKEY_ACTION_NUMERIC_COMPARISON4
Confirmar que o passkey corresponde ao mostrado no dispositivo remoto.
Para poupar espaço no firmware, estas constantes não estão incluídas no módulo
bluetooth. Adicione ao seu programa as que precisar das listas acima.
Papel de Transmissor (Anunciante)
- gap_advertise(interval_us: int | None, adv_data: bytes | None = None, *, resp_data: bytes | None = None, connectable: bool = True) None¶
Inicia a publicidade no intervalo especificado (em microssegundos). Este intervalo será arredondado para baixo ao múltiplo de 625 µs mais próximo. Para parar a publicidade, defina interval_us como
None.adv_data e resp_data podem ser de qualquer tipo que implemente o protocolo de buffer (por exemplo,
bytes,bytearray,str). adv_data é incluído em todas as transmissões, e resp_data é enviado em resposta a uma pesquisa ativa.Nota: se adv_data (ou resp_data) for
None, os dados passados na chamada anterior agap_advertiseserão reutilizados. Isto permite que um transmissor retome a publicidade apenas comgap_advertise(interval_us). Para limpar o payload de publicidade, passebytesvazio, isto é,b''.
Papel de Observador (Scanner)
- gap_scan(duration_ms: int | None, interval_us: int = 1280000, window_us: int = 11250, active: bool = False, /) None¶
Executa uma operação de pesquisa com a duração especificada (em milissegundos).
Para pesquisar indefinidamente, defina duration_ms como
0.Para parar a pesquisa, defina duration_ms como
None.Utilize interval_us e window_us para configurar opcionalmente o ciclo de trabalho. O scanner funcionará durante window_us microssegundos a cada interval_us microssegundos, durante um total de duration_ms milissegundos. O intervalo e a janela por defeito são 1,28 segundos e 11,25 milissegundos, respetivamente (pesquisa em segundo plano).
Para cada resultado de pesquisa, o evento
_IRQ_SCAN_RESULTserá gerado, com dados de evento(addr_type, addr, adv_type, rssi, adv_data).Os valores de
addr_typeindicam endereços públicos ou aleatórios:Valor
Nome
Significado
0x00PUBLIC
Endereço público do dispositivo.
0x01RANDOM
Endereço aleatório (estático, RPA ou NRPA; o tipo está codificado no próprio endereço).
Os valores de
adv_typecorrespondem à Especificação Bluetooth:Valor
Nome
Significado
0x00ADV_IND
Publicidade não direcionada ligável e pesquisável.
0x01ADV_DIRECT_IND
Publicidade direcionada ligável.
0x02ADV_SCAN_IND
Publicidade não direcionada pesquisável.
0x03ADV_NONCONN_IND
Publicidade não direcionada não ligável.
0x04SCAN_RSP
Resposta de pesquisa.
activepode ser definido comoTruese quiser receber respostas de pesquisa nos resultados.Quando a pesquisa for parada (seja por conclusão da duração ou por paragem explícita), o evento
_IRQ_SCAN_DONEserá gerado.
Papel de Central
Um dispositivo central pode ligar-se a periféricos que descobriu utilizando o papel de observador (consulte
gap_scan) ou com um endereço conhecido.- gap_connect(addr_type: int | None, addr: bytes | None = None, scan_duration_ms: int = 2000, min_conn_interval_us: int | None = None, max_conn_interval_us: int | None = None, /) None¶
Ligar a um periférico.
Consulte
gap_scanpara detalhes sobre os tipos de endereço.Para cancelar antecipadamente uma tentativa de ligação pendente, chame
gap_connect(None).Em caso de sucesso, o evento
_IRQ_PERIPHERAL_CONNECTserá gerado. Ao cancelar uma tentativa de ligação, o evento_IRQ_PERIPHERAL_DISCONNECTserá gerado.O dispositivo aguardará até scan_duration_ms para receber um payload de publicidade do dispositivo.
O intervalo de ligação pode ser configurado em microssegundos usando min_conn_interval_us e/ou max_conn_interval_us. Caso contrário, será escolhido um intervalo por defeito, tipicamente entre 30000 e 50000 microssegundos. Um intervalo mais curto aumentará o débito, à custa do consumo de energia.
Papel de Periférico
Espera-se que um dispositivo periférico envie publicidade ligável (consulte
gap_advertise). Normalmente actuará como servidor GATT, tendo previamente registado serviços e características comgatts_register_services.Quando um central se liga, o evento
_IRQ_CENTRAL_CONNECTserá gerado.Papéis de Central e Periférico
- gap_disconnect(conn_handle: int, /) bool¶
Desliga o handle de ligação especificado. Pode ser um central que se ligou a este dispositivo (se a agir como periférico) ou um periférico ao qual este dispositivo se ligou anteriormente (se a agir como central).
Em caso de sucesso, o evento
_IRQ_PERIPHERAL_DISCONNECTou_IRQ_CENTRAL_DISCONNECTserá gerado.Devolve
Falsese o handle de ligação não estava ligado, eTruecaso contrário.
Servidor GATT
Um servidor GATT possui um conjunto de serviços registados. Cada serviço pode conter características, e cada uma tem um valor. As características também podem conter descritores, que por sua vez têm valores.
Estes valores são armazenados localmente e acedidos através do seu «value handle», gerado durante o registo do serviço. Também podem ser lidos ou escritos por um dispositivo cliente remoto. Adicionalmente, um servidor pode «notificar» uma característica a um cliente ligado através de um handle de ligação.
Um dispositivo nos papéis de central ou periférico pode funcionar como servidor GATT; no entanto, na maioria dos casos, é mais comum que um dispositivo periférico atue como servidor.
As características e descritores têm um tamanho máximo por defeito de 20 bytes (o MTU ATT por defeito de 23 bytes menos um cabeçalho ATT de 3 bytes; um MTU negociado superior não aumenta automaticamente este limite). Qualquer escrita feita por um cliente será truncada para este comprimento. No entanto, qualquer escrita local aumentará o tamanho máximo; portanto, se pretender permitir escritas maiores por parte de um cliente numa dada característica, utilize
gatts_writeapós o registo. Por exemplo:gatts_write(char_handle, bytes(100)).- gatts_register_services(services_definition: Sequence[Sequence], /) Sequence[Sequence[int]]¶
Configura o servidor com os serviços especificados, substituindo quaisquer serviços existentes.
services_definition é uma lista de serviços, em que cada serviço é um tuplo de dois elementos contendo um UUID e uma lista de características.
Cada característica é um tuplo de dois ou três elementos contendo um UUID, um valor de flags e, opcionalmente, uma lista de descritores.
Cada descritor é um tuplo de dois elementos contendo um UUID e um valor de flags.
As flags são uma combinação bit a bit (OR) das flags definidas abaixo. Estas definem tanto o comportamento da característica (ou descritor) como os requisitos de segurança e privacidade.
O valor de retorno é uma lista (um elemento por serviço) de tuplos (cada elemento é um value handle). Os handles de características e descritores são nivelados no mesmo tuplo, pela ordem em que são definidos.
O exemplo seguinte regista dois serviços (Heart Rate e Nordic UART):
bt = bluetooth.BLE() bt.active(True) # Heart Rate service: one Heart Rate Measurement characteristic. HR_SERVICE = ( bluetooth.UUID(0x180D), ( (bluetooth.UUID(0x2A37), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY), ), ) # Nordic UART service: a TX characteristic the client subscribes # to for notifications, and an RX characteristic it writes to. UART_SERVICE = ( bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E'), ( (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY), (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_WRITE), ), ) ((hr,), (tx, rx)) = bt.gatts_register_services( (HR_SERVICE, UART_SERVICE), )
Os três value handles (
hr,tx,rx) podem ser utilizados comgatts_read,gatts_write,gatts_notifyegatts_indicate.Nota: A publicidade deve ser parada antes de registar serviços.
As flags disponíveis para características e descritores são:
Constante
Valor
Significado
_FLAG_BROADCAST0x0001A característica pode ser transmitida.
_FLAG_READ0x0002O cliente pode ler o valor.
_FLAG_WRITE_NO_RESPONSE0x0004O cliente pode escrever sem aguardar resposta.
_FLAG_WRITE0x0008O cliente pode escrever com resposta de confirmação.
_FLAG_NOTIFY0x0010O servidor pode enviar notificações (não reconhecidas).
_FLAG_INDICATE0x0020O servidor pode enviar indicações (reconhecidas).
_FLAG_AUTHENTICATED_SIGNED_WRITE0x0040O cliente pode emitir escritas assinadas.
_FLAG_AUX_WRITE0x0100Propriedades estendidas: escritas em fila/fiáveis são permitidas.
_FLAG_READ_ENCRYPTED0x0200A leitura requer uma ligação encriptada.
_FLAG_READ_AUTHENTICATED0x0400A leitura requer uma ligação autenticada (com proteção MITM).
_FLAG_READ_AUTHORIZED0x0800A leitura requer autorização ao nível da aplicação.
_FLAG_WRITE_ENCRYPTED0x1000A escrita requer uma ligação encriptada.
_FLAG_WRITE_AUTHENTICATED0x2000A escrita requer uma ligação autenticada (com proteção MITM).
_FLAG_WRITE_AUTHORIZED0x4000A escrita requer autorização ao nível da aplicação.
Tal como as constantes de eventos acima, estas flags não são fornecidas pelo módulo
bluetooth; copie as que precisar para o seu programa.
- gatts_read(value_handle: int, /) bytes¶
Lê o valor local para este handle (que tanto pode ter sido escrito por
gatts_writecomo por um cliente remoto).
- gatts_write(value_handle: int, data: bytes, send_update: bool = False, /) None¶
Escreve o valor local para este handle, que pode ser lido por um cliente.
Se send_update for
True, todos os clientes subscritos serão notificados (ou indicados, consoante o que estejam subscritos e as operações que a característica suporta) acerca desta escrita.
- gatts_notify(conn_handle: int, value_handle: int, data: bytes | None = None, /) None¶
Envia um pedido de notificação a um cliente ligado.
Se data for
None(o padrão), o valor local atual (conforme definido comgatts_write) será enviado.Caso contrário, se data não for
None, esse valor é enviado ao cliente como parte da notificação. O valor local não será modificado.Nota: A notificação será enviada independentemente do estado de subscrição do cliente a esta característica.
- gatts_indicate(conn_handle: int, value_handle: int, data: bytes | None = None, /) None¶
Envia um pedido de indicação a um cliente ligado.
Se data for
None(o padrão), o valor local atual (conforme definido comgatts_write) será enviado.Caso contrário, se data não for
None, esse valor é enviado ao cliente como parte da indicação. O valor local não será modificado.Após o reconhecimento (ou falha, por exemplo, timeout), o evento
_IRQ_GATTS_INDICATE_DONEserá gerado.Nota: A indicação será enviada independentemente do estado de subscrição do cliente a esta característica.
- gatts_set_buffer(value_handle: int, len: int, append: bool = False, /) None¶
Define o tamanho do buffer interno para um valor em bytes. Isto limitará o maior write possível que pode ser recebido. O valor por defeito é 20 bytes (MTU ATT por defeito de 23 menos o cabeçalho ATT de 3 bytes).
Definir append como
Truefará com que todas as escritas remotas sejam adicionadas ao, em vez de substituírem o, valor atual. No máximo len bytes podem ser armazenados desta forma. Ao utilizargatts_read, o valor será limpo após a leitura. Esta funcionalidade é útil ao implementar algo como o Nordic UART Service.
Cliente GATT
Um cliente GATT pode descobrir e ler/escrever características num servidor GATT remoto.
É mais comum que um dispositivo no papel de central atue como cliente GATT; no entanto, também é possível que um periférico atue como cliente para descobrir informações sobre o central que se ligou a ele (por exemplo, para ler o nome do dispositivo a partir do serviço de informação do dispositivo).
- gattc_discover_services(conn_handle: int, uuid: UUID | None = None, /) None¶
Consulta os serviços de um servidor ligado.
Opcionalmente, especifique um uuid de serviço para consultar apenas esse serviço.
Para cada serviço descoberto, o evento
_IRQ_GATTC_SERVICE_RESULTserá gerado, seguido de_IRQ_GATTC_SERVICE_DONEna conclusão.
- gattc_discover_characteristics(conn_handle: int, start_handle: int, end_handle: int, uuid: UUID | None = None, /) None¶
Consulta as características de um servidor ligado no intervalo especificado.
Opcionalmente, especifique um uuid de característica para consultar apenas essa característica.
Passar
start_handle=1eend_handle=0xffffcobre o intervalo completo de handles de atributos GATT, pesquisando efetivamente todos os serviços no dispositivo remoto.Para cada característica descoberta, o evento
_IRQ_GATTC_CHARACTERISTIC_RESULTserá gerado, seguido de_IRQ_GATTC_CHARACTERISTIC_DONEna conclusão.
- gattc_discover_descriptors(conn_handle: int, start_handle: int, end_handle: int, /) None¶
Consulta os descritores de um servidor ligado no intervalo especificado.
Para cada descritor descoberto, o evento
_IRQ_GATTC_DESCRIPTOR_RESULTserá gerado, seguido de_IRQ_GATTC_DESCRIPTOR_DONEna conclusão.
- gattc_read(conn_handle: int, value_handle: int, /) None¶
Emite uma leitura remota num servidor ligado para o handle de característica ou descritor especificado.
Quando um valor estiver disponível, o evento
_IRQ_GATTC_READ_RESULTserá gerado, seguido de_IRQ_GATTC_READ_DONEna conclusão.
- gattc_write(conn_handle: int, value_handle: int, data: bytes, mode: int = 0, /) None¶
Emite uma escrita remota num servidor ligado para o handle de característica ou descritor especificado.
O argumento mode especifica o comportamento de escrita, sendo os valores atualmente suportados:
mode=0(padrão) é uma escrita sem resposta: a escrita será enviada para o servidor remoto mas nenhuma confirmação será devolvida e nenhum evento será gerado.mode=1é uma escrita com resposta: o servidor remoto é solicitado a enviar uma resposta/reconhecimento de que recebeu os dados.
Se uma resposta for recebida do servidor remoto, o evento
_IRQ_GATTC_WRITE_DONEserá gerado.
- gattc_exchange_mtu(conn_handle: int, /) None¶
Inicia a troca de MTU com um servidor ligado, utilizando o MTU preferido definido com
BLE.config(mtu=value).O evento
_IRQ_MTU_EXCHANGEDserá gerado quando a troca de MTU for concluída.A troca de MTU é tipicamente iniciada pelo central; NimBLE suporta ambos os papéis.
Canais L2CAP Orientados a Ligação
Esta funcionalidade permite a troca de dados semelhante a sockets entre dois dispositivos BLE. Uma vez ligados os dispositivos via GAP, qualquer dispositivo pode aguardar que o outro se ligue num PSM (Protocol/Service Multiplexer) numérico.
Apenas um canal L2CAP pode estar ativo em dado momento (ou seja, não é possível ligar enquanto se está à escuta).
Os canais L2CAP ativos são identificados pelo handle de ligação em que foram estabelecidos e por um CID (channel ID).
Os canais orientados a ligação têm controlo de fluxo baseado em créditos incorporado. Ao contrário do ATT, onde os dispositivos negoceiam um MTU partilhado, tanto o dispositivo que escuta como o que se liga definem um MTU independente que limita a quantidade máxima de dados pendentes que o dispositivo remoto pode enviar antes de serem totalmente consumidos em
l2cap_recvinto.- l2cap_listen(psm: int, mtu: int, /) None¶
Começa a aguardar pedidos de canal L2CAP de entrada no psm especificado com o MTU local definido como mtu.
Quando um dispositivo remoto inicia uma ligação, o evento
_IRQ_L2CAP_ACCEPTserá gerado, dando ao servidor que escuta a oportunidade de rejeitar a ligação de entrada (devolvendo um inteiro não nulo).Uma vez aceite a ligação, o evento
_IRQ_L2CAP_CONNECTserá gerado, permitindo ao servidor obter o CID e os MTU local e remoto.Nota: Não é atualmente possível parar de escutar.
- l2cap_connect(conn_handle: int, psm: int, mtu: int, /) None¶
Liga a um par que está à escuta no psm especificado com o MTU local definido como mtu.
Em caso de ligação bem-sucedida, o evento
_IRQ_L2CAP_CONNECTserá gerado, permitindo ao cliente obter o CID e os MTU local e remoto (peer).Uma ligação sem sucesso gerará o evento
_IRQ_L2CAP_DISCONNECTcom um status não nulo.
- l2cap_disconnect(conn_handle: int, cid: int, /) None¶
Desliga um canal L2CAP ativo com o conn_handle e cid especificados.
- l2cap_send(conn_handle: int, cid: int, buf: bytes, /) bool¶
Envia o buf especificado (que deve suportar o protocolo de buffer) no canal L2CAP identificado por conn_handle e cid.
O buffer deve satisfazer ambos os limites: não deve exceder o MTU remoto (peer) e não deve exceder o dobro do MTU local.
Isto devolverá
Falsese o canal estiver agora «bloqueado», o que significa quel2cap_sendnão deve ser chamado novamente até que o evento_IRQ_L2CAP_SEND_READYseja recebido (o que acontecerá quando o dispositivo remoto conceder mais créditos, tipicamente após ter recebido e processado os dados).
- l2cap_recvinto(conn_handle: int, cid: int, buf: Any | None, /) int¶
Recebe dados do conn_handle e cid especificados para o buf fornecido (que deve suportar o protocolo de buffer, por exemplo, bytearray ou memoryview).
Devolve o número de bytes lidos do canal.
Se buf for
None, devolve o número de bytes disponíveis.Nota: Após receber o evento
_IRQ_L2CAP_RECV, a aplicação deve continuar a chamarl2cap_recvintoaté que não haja mais bytes disponíveis no buffer de receção (tipicamente até ao tamanho do MTU remoto (peer)).Enquanto o buffer de receção não estiver vazio, o dispositivo remoto não receberá mais créditos de canal e não conseguirá enviar mais dados.
Emparelhamento e Vinculação
O emparelhamento permite que uma ligação seja encriptada e autenticada através da troca de segredos (com proteção MITM opcional via autenticação por passkey).
A vinculação é o processo de armazenar esses segredos em armazenamento não volátil. Quando vinculado, um dispositivo consegue resolver um endereço privado resolúvel (RPA) de outro dispositivo com base na chave de resolução de identidade (IRK) armazenada. Para suportar a vinculação, uma aplicação deve implementar os eventos
_IRQ_GET_SECRETe_IRQ_SET_SECRET.- gap_pair(conn_handle: int, /) None¶
Inicia o emparelhamento com o dispositivo remoto.
Antes de chamar isto, certifique-se de que as opções de configuração
io,mitm,le_secureebondestão definidas (viaconfig).Em caso de emparelhamento bem-sucedido, o evento
_IRQ_ENCRYPTION_UPDATEserá gerado.
- gap_passkey(conn_handle: int, action: int, passkey: int, /) None¶
Responde a um evento
_IRQ_PASSKEY_ACTIONpara o conn_handle e action especificados. O significado de passkey depende de action (que por sua vez depende da capacidade de I/O configurada):Ação
Resposta de passkey necessária
_PASSKEY_ACTION_INPUTO passkey que o utilizador lê do dispositivo remoto.
_PASSKEY_ACTION_DISPLAYUm passkey aleatório de 6 dígitos gerado localmente e mostrado ao utilizador.
_PASSKEY_ACTION_NUMERIC_COMPARISON1para aceitar o passkey mostrado no evento_IRQ_PASSKEY_ACTION, ou0para cancelar o emparelhamento.
class UUID¶
- class bluetooth.UUID(value: int | bytes | str, /)¶
Cria uma instância UUID com o
valueespecificado. O Bluetooth usa três larguras de UUID;UUIDaceita qualquer uma delas:Largura de UUID
Tipos de
valueaceitesExemplo
16 bits
intou um buffer de 2 bytes (little-endian)UUID(0x2908)ouUUID(b'\x08\x29')32 bits
buffer de 4 bytes (little-endian)
UUID(b'\x08\x29\x00\x00')128 bits
buffer de 16 bytes ou uma string com hífens
UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')Os UUIDs de 16 e 32 bits são tipicamente identificadores atribuídos pelo SIG (consulte os números atribuídos Bluetooth); os UUIDs de 128 bits são normalmente definidos pelo fornecedor.