aioble — BLE Assíncrono¶
aioble é um invólucro de alto nível compatível com asyncio para o módulo bluetooth. Fornece corrotinas limpas para digitalização, ligação, publicidade, serviços GATT e canais L2CAP.
Todas as operações remotas (ligar, desligar, leitura/escrita do cliente, indicação do servidor, receção/envio l2cap, emparelhamento) são aguardáveis e suportam tempos limite.
Funções suportadas:
Difusor (anunciante) — gera payloads de publicidade e de resposta a digitalização para campos comuns, divide automaticamente o payload entre publicidade e resposta a digitalização, anuncia indefinidamente ou por uma duração fixa.
Periférico — aguarda ligação de um central, aguarda troca de MTU.
Observador (scanner) — digitalização passiva e ativa, combina payloads de publicidade e de resposta a digitalização para o mesmo dispositivo, analisa campos comuns a partir dos payloads de publicidade.
Central — liga-se a um periférico, inicia troca de MTU.
Cliente GATT — descobre serviços / características / descritores (opcionalmente por UUID); leitura / escrita / escrita-com-resposta em características e descritores; subscreve notificações e indicações (via CCCD); aguarda notificações e indicações.
Servidor GATT — regista serviços / características / descritores; aguarda escritas em características e descritores; interceta pedidos de leitura; envia notificações e indicações (e aguarda resposta).
L2CAP — aceita e liga canais L2CAP orientados à ligação, gere o controlo de fluxo do canal.
Segurança — gestão de chaves/segredos com suporte JSON, inicia emparelhamento, consulta estado de encriptação / autenticação.
Exemplos¶
Digitalizar dispositivos BLE próximos e imprimir cada um à medida que é detetado:
import aioble
import asyncio
async def find_devices():
async with aioble.scan(duration_ms=5000, active=True) as scanner:
async for result in scanner:
print(result.device.addr_hex(), result.rssi, result.name())
asyncio.run(find_devices())
Ligar a um periférico que anuncia o serviço de Frequência Cardíaca como central e subscrever as suas notificações de medição:
import aioble
import asyncio
import bluetooth
_HR_SERVICE = bluetooth.UUID(0x180D)
_HR_MEASUREMENT = bluetooth.UUID(0x2A37)
async def connect_and_read():
device = None
async with aioble.scan(duration_ms=5000, active=True) as scanner:
async for result in scanner:
if _HR_SERVICE in result.services():
device = result.device
break
if device is None:
return
async with await device.connect() as conn:
service = await conn.service(_HR_SERVICE)
char = await service.characteristic(_HR_MEASUREMENT)
await char.subscribe(notify=True)
while True:
data = await char.notified()
print("notify:", data)
asyncio.run(connect_and_read())
Atuar como periférico: registar um serviço GATT, anunciá-lo e enviar notificações a quem se ligar:
import aioble
import asyncio
import bluetooth
import struct
_ENV_SERVICE = bluetooth.UUID(0x181A)
_TEMP_CHAR = bluetooth.UUID(0x2A6E)
def encode_temperature(deg_c):
# Bluetooth Temperature (0x2A6E) is sint16 little-endian, 0.01 degC units.
return struct.pack("<h", round(deg_c * 100))
service = aioble.Service(_ENV_SERVICE)
temp_char = aioble.Characteristic(service, _TEMP_CHAR, read=True, notify=True)
aioble.register_services(service)
async def peripheral_task():
while True:
connection = await aioble.advertise(
interval_us=250000,
name="openmv-sensor",
services=[_ENV_SERVICE],
appearance=0x0300,
)
print("connected:", connection.device.addr_hex())
async with connection:
while connection.is_connected():
temp_char.write(encode_temperature(23.68), send_update=True)
await asyncio.sleep(1)
asyncio.run(peripheral_task())
Funções ao nível do módulo¶
- aioble.config(*args, **kwargs) Any¶
Redireciona para
bluetooth.BLE.config(), garantindo que o rádio BLE está ativo primeiro.- args
Nome de parâmetro único opcional a consultar.
- kwargs
Argumentos de palavra-chave para definir valores de configuração.
- aioble.stop() None¶
Desativa o rádio BLE subjacente e executa quaisquer manipuladores de encerramento de sub-módulos registados. Após chamar isto, scanners, anunciantes, ligações e canais L2CAP são todos encerrados.
- aioble.scan(duration_ms: int, interval_us: int | None = None, window_us: int | None = None, active: bool = False) scan¶
Devolve um gestor de contexto assíncrono / iterador assíncrono
scanque produz instânciasScanResultpara cada dispositivo único descoberto (ou para cada novo dado de publicidade de um dispositivo conhecido).- duration_ms
Duração da digitalização, em milissegundos. Passe
0para digitalizar indefinidamente até o gestor de contexto sair.- interval_us
Intervalo de digitalização em microssegundos. Predefinição: 1.280.000.
- window_us
Janela de digitalização em microssegundos (deve ser menor ou igual a interval_us). Predefinição: 11.250.
- active
Se
True, realiza uma digitalização ativa (solicita dados de resposta a digitalização). Predefinição:False.
- aioble.advertise(interval_us: int, adv_data: bytes | None = None, resp_data: bytes | None = None, connectable: bool = True, limited_disc: bool = False, br_edr: bool = False, name: str | None = None, services: list | None = None, appearance: int = 0, manufacturer: tuple | None = None, timeout_ms: int | None = None) DeviceConnection¶
Corrotina assíncrona que inicia a publicidade e aguarda uma ligação central de entrada. Devolve uma
DeviceConnectionrepresentando o central ligado, ou lançaasyncio.TimeoutErrorem caso de tempo limite.- interval_us
Intervalo de publicidade, em microssegundos.
- adv_data
Payload de publicidade em bruto. Se não definido, adv_data é construído a partir dos restantes argumentos de palavra-chave.
- resp_data
Payload de resposta a digitalização em bruto. Preenchido automaticamente com o excesso de adv_data se necessário.
- connectable
Se
True, este é um anúncio ligável.- limited_disc
Usa a flag de descoberta limitada em vez da geral.
- br_edr
Define a flag de suporte a BR/EDR.
- name
Nome local completo opcional a incluir.
- services
Iterável de
bluetooth.UUIDa anunciar.- appearance
Valor de aparência de 16 bits (ver números atribuídos Bluetooth).
- manufacturer
Tuplo de
(company_id, data_bytes)a anunciar como dados específicos do fabricante.- timeout_ms
Pára a publicidade após este número de milissegundos sem uma ligação.
Nonesignifica anunciar até haver ligação.
Constantes ao nível do módulo¶
- aioble.ADDR_PUBLIC¶
Tipo de endereço de dispositivo BLE público (
0).
- aioble.ADDR_RANDOM¶
Tipo de endereço de dispositivo BLE aleatório (
1).
Exceções¶
- exception aioble.GattError¶
Lançada quando uma operação GATT remota (leitura / escrita / indicação) termina com um estado não nulo. O código de estado está disponível no atributo
_status.
- exception aioble.DeviceDisconnectedError¶
Lançada dentro de uma operação assíncrona (p.ex. leitura, escrita, notificação) quando a ligação subjacente cai enquanto aguarda.
- exception aioble.L2CAPDisconnectedError¶
Lançada quando se tenta uma operação de envio/receção/descarga num canal L2CAP sobre um canal desligado (ou interrompida por ele).
- exception aioble.L2CAPConnectionError¶
Lançada por
DeviceConnection.l2cap_connectquando o estabelecimento do canal falha. O código de estado Bluetooth é o primeiro argumento.
Classes¶
- class aioble.Device(addr_type: int, addr: bytes | str)¶
Representa um dispositivo BLE remoto pelo endereço. Duas instâncias
Devicesão iguais se tanto addr_type como addr coincidirem. Usado como identificador para iniciar ligações.- addr_type
Pode ser
ADDR_PUBLICouADDR_RANDOM.- addr
Endereço de seis bytes como
bytes, ou uma cadeia hexadecimal separada por dois-pontos (p.ex."aa:bb:cc:dd:ee:ff").
- addr_type¶
O tipo de endereço com que o dispositivo foi construído.
- addr¶
O endereço bruto de seis bytes do dispositivo.
- connect(timeout_ms: int = 10000, scan_duration_ms: int | None = None, min_conn_interval_us: int | None = None, max_conn_interval_us: int | None = None) Awaitable[DeviceConnection]¶
Assíncrono. Inicia uma ligação GAP a este dispositivo e devolve a
DeviceConnectionresultante. Cancela qualquer digitalização em curso.- timeout_ms
Tempo a aguardar para a ligação ser concluída.
- scan_duration_ms
Duração de digitalização inicial antes de ligar (específico do controlador).
- min_conn_interval_us / max_conn_interval_us
Limites opcionais do intervalo de ligação, em microssegundos.
- class aioble.DeviceConnection¶
Uma ligação GAP ativa a um
Device. Devolvida porDevice.connect()ouadvertise. Suporta utilização como gestor de contextoasync withque desliga automaticamente ao sair.Não construir diretamente.
- encrypted¶
Trueassim que a ligação está encriptada (p.ex. após emparelhamento).
- authenticated¶
Truese a ligação foi autenticada (emparelhamento com proteção MITM).
- bonded¶
Truese o emparelhamento produziu chaves de vinculação.
- key_size¶
Tamanho negociado da chave de encriptação em bytes, ou
Falsese não estiver encriptada.
- mtu¶
MTU ATT negociado após
exchange_mtu, ouNoneaté ser definido.
- disconnect(timeout_ms: int = 2000) Awaitable[None]¶
Assíncrono. Desliga e aguarda o IRQ de desligação.
- timeout_ms
Tempo máximo a aguardar pela desligação.
- disconnected(timeout_ms: int | None = None, disconnect: bool = False) Awaitable[None]¶
Assíncrono. Aguarda que a ligação seja terminada por qualquer um dos lados. Se disconnect for
True, desliga ativamente primeiro.- timeout_ms
Tempo máximo a aguardar.
Nonesignifica aguardar indefinidamente.- disconnect
Se
True, inicia a desligação.
- timeout(timeout_ms: int | None) DeviceTimeout¶
Devolve um gestor de contexto que cancela o seu corpo se o tempo limite expirar (lançando
asyncio.TimeoutError) ou se o dispositivo se desligar (lançandoDeviceDisconnectedError).- timeout_ms
Tempo limite em milissegundos, ou
Nonesem tempo limite.
- exchange_mtu(mtu: int | None = None, timeout_ms: int = 1000) Awaitable[int]¶
Assíncrono. Inicia uma troca de MTU ATT e devolve o MTU negociado.
- mtu
MTU preferido opcional a definir na interface BLE subjacente antes da troca.
- timeout_ms
Tempo limite para a troca.
- service(uuid: bluetooth.UUID, timeout_ms: int = 2000) Awaitable[ClientService | None]¶
Assíncrono. Descobre um único serviço remoto correspondente a uuid, ou
Nonese não for encontrado.
- services(uuid: bluetooth.UUID | None = None, timeout_ms: int = 2000) ClientDiscover¶
Devolve um iterador assíncrono de objetos
ClientServiceremotos. Use comasync fore execute o ciclo até à conclusão.- uuid
Filtro UUID opcional.
Nonedevolve todos os serviços.- timeout_ms
Tempo limite por descoberta.
- pair(bond: bool = True, le_secure: bool = True, mitm: bool = False, io: int = 3, timeout_ms: int = 20000) Awaitable[None]¶
Assíncrono. Inicia o emparelhamento nesta ligação. Atualiza os atributos
encrypted/authenticated/bonded/key_sizequando concluído.- bond
Persiste as chaves de emparelhamento.
- le_secure
Usa Ligações Seguras LE.
- mitm
Requer proteção contra ataques man-in-the-middle.
- io
Constante de capacidade de E/S (p.ex.
3para sem entrada/saída).- timeout_ms
Tempo limite de emparelhamento.
- l2cap_accept(psm: int, mtu: int, timeout_ms: int | None = None) Awaitable[L2CAPChannel]¶
Assíncrono. Escuta no PSM indicado e devolve um
L2CAPChannelassim que o remoto o abrir.- psm
Multiplexador de Protocolo/Serviço a escutar.
- mtu
Tamanho máximo de receção, em bytes.
- timeout_ms
Tempo máximo a aguardar que o remoto se ligue.
- l2cap_connect(psm: int, mtu: int, timeout_ms: int = 1000) Awaitable[L2CAPChannel]¶
Assíncrono. Abre um canal L2CAP para o remoto no PSM indicado.
- psm
Multiplexador de Protocolo/Serviço a ligar.
- mtu
Tamanho máximo de receção, em bytes.
- timeout_ms
Tempo limite da ligação.
- class aioble.ScanResult¶
Um único dispositivo descoberto durante
scan. A mesma instância é re-produzida à medida que chegam novos dados de publicidade.Não construir diretamente.
- rssi¶
Último RSSI reportado, em dBm.
- adv_data¶
Payload de publicidade em bruto (
bytesouNone).
- resp_data¶
Payload de resposta a digitalização em bruto (
bytesouNone), se a digitalização ativa estiver ativada.
- connectable¶
Truese o anúncio mais recente foi ligável.
- name() str | None¶
Descodifica o nome local anunciado completo (ou abreviado) a partir do payload, ou
Nonese não estiver presente.
- services() Iterator[bluetooth.UUID]¶
Gerador que produz cada
bluetooth.UUIDanunciado nos campos de lista de serviços de 16/32/128 bits.
- class aioble.Service(uuid: bluetooth.UUID)¶
Um serviço GATT local. Crie um serviço com uma ou mais instâncias
Characteristic, depois passe-o pararegister_services.- uuid
O UUID do serviço.
- uuid¶
O UUID do serviço.
- characteristics¶
Lista de objetos
Characteristicassociados a este serviço.
- class aioble.Characteristic(service: Service, uuid: bluetooth.UUID, read: bool = False, write: bool = False, write_no_response: bool = False, notify: bool = False, indicate: bool = False, initial: bytes | None = None, capture: bool = False)¶
Uma característica GATT local. Construir uma appende-a automaticamente a service.
- service
O
Serviceproprietário.- uuid
O UUID da característica.
- read, write, write_no_response, notify, indicate
Booleanos que selecionam as operações GATT suportadas.
- initial
Valor inicial opcional (
bytes).- capture
Se
True, os valores escritos são colocados em fila (até 10) para que escritas consecutivas rápidas não se percam. Cada chamadawrittendevolve então um tuplo(connection, data).
- uuid¶
O UUID da característica.
- flags¶
Máscara de bits das flags de propriedade GATT construída a partir do construtor.
- descriptors¶
Lista de objetos
Descriptorassociados a esta característica.
- write(data: bytes, send_update: bool = False) None¶
Atualiza o valor na base de dados GATT local.
- data
Novos bytes de valor.
- send_update
Se
True, também notifica/indica cada ligação subscrita.
- notify(connection: DeviceConnection, data: bytes | None = None) None¶
Envia uma Notificação GATT para connection.
- connection
A ligação do cliente alvo.
- data
Payload a enviar. Se
None, o valor local atual é enviado.
- indicate(connection: DeviceConnection, data: bytes | None = None, timeout_ms: int = 1000) Awaitable[None]¶
Assíncrono. Envia uma Indicação GATT para connection e aguarda a confirmação do cliente. Lança
GattErrorem caso de estado não nulo.- connection
A ligação do cliente alvo.
- data
Payload a indicar, ou
Nonepara enviar o valor local.- timeout_ms
Tempo máximo a aguardar confirmação.
- written(timeout_ms: int | None = None) Awaitable[DeviceConnection | tuple[DeviceConnection, bytes]]¶
Assíncrono. Aguarda uma escrita remota. Devolve a
DeviceConnectionque escreveu, ou(connection, data)se a característica foi criada comcapture=True.- timeout_ms
Tempo máximo a aguardar.
Noneaguarda indefinidamente.
- on_read(connection: DeviceConnection) int¶
Função hook invocada de forma síncrona quando é recebida uma leitura remota. Devolve
0para permitir a leitura ou um código de erro ATT não nulo para rejeitá-la. A implementação predefinida devolve0.
- class aioble.BufferedCharacteristic(service: Service, uuid: bluetooth.UUID, max_len: int = 20, append: bool = False, **kwargs)¶
Uma
Characteristiccujo buffer GATT de suporte pode ser configurado. Útil para receber valores maiores do que o tamanho padrão do atributo, ou para colocar em fila escritas consecutivas.- max_len
Tamanho do buffer, em bytes.
- append
Se
True, escritas sequenciais acrescentam ao buffer em vez de sobrescrever.
Outros argumentos são passados para
Characteristic.
- class aioble.Descriptor(characteristic: Characteristic, uuid: bluetooth.UUID, read: bool = False, write: bool = False, initial: bytes | None = None)¶
Um descritor GATT local. Construir um appende-o automaticamente a characteristic. Herda
read,writeewrittendeCharacteristic.- characteristic
A
Characteristicproprietária.- uuid
O UUID do descritor.
- read, write
Booleanos que selecionam as operações GATT suportadas.
- initial
Valor inicial opcional (
bytes).
- class aioble.ClientService¶
Um serviço GATT remoto descoberto num par. Devolvido por
DeviceConnection.service()ou iterado a partir deDeviceConnection.services().Não construir diretamente.
- connection¶
A
DeviceConnectionproprietária.
- uuid¶
O UUID do serviço remoto.
- characteristic(uuid: bluetooth.UUID, timeout_ms: int = 2000) Awaitable[ClientCharacteristic | None]¶
Assíncrono. Descobre uma única característica por UUID, ou
Nonese não for encontrada.
- characteristics(uuid: bluetooth.UUID | None = None, timeout_ms: int = 2000) ClientDiscover¶
Devolve um iterador assíncrono de objetos
ClientCharacteristic. Use comasync fore execute o ciclo até à conclusão.- uuid
Filtro UUID opcional.
- timeout_ms
Tempo limite por descoberta.
- class aioble.ClientCharacteristic¶
Uma característica GATT remota descoberta num par. Devolvida por
ClientService.characteristic()ou iterada a partir deClientService.characteristics().Não construir diretamente.
- service¶
O
ClientServiceproprietário.
- uuid¶
O UUID da característica.
- properties¶
Máscara de bits das operações GATT suportadas conforme reportado pelo par.
- read(timeout_ms: int = 1000) Awaitable[bytes]¶
Assíncrono. Emite uma Leitura GATT e devolve o valor. Lança
GattErrorem caso de estado não nulo.- timeout_ms
Tempo limite de leitura.
- write(data: bytes, response: bool | None = None, timeout_ms: int = 1000) Awaitable[None]¶
Assíncrono. Emite uma Escrita GATT.
- data
Valor a escrever.
- response
Truepara exigir uma resposta de escrita (e lançarGattErrorem caso de falha).Falsepara escrita-sem-resposta.None(predefinição) seleciona automaticamente com base no que o par anuncia.- timeout_ms
Tempo limite de escrita (apenas relevante se response for
True).
- notified(timeout_ms: int | None = None) Awaitable[bytes]¶
Assíncrono. Aguarda a próxima notificação nesta característica e devolve o seu payload. Devolve imediatamente se já houver uma notificação em fila.
- timeout_ms
Tempo máximo a aguardar.
Noneaguarda indefinidamente.
- indicated(timeout_ms: int | None = None) Awaitable[bytes]¶
Assíncrono. Aguarda a próxima indicação nesta característica e devolve o seu payload.
- timeout_ms
Tempo máximo a aguardar.
- subscribe(notify: bool = True, indicate: bool = False) Awaitable[None]¶
Assíncrono. Escreve o Descritor de Configuração de Característica do Cliente (CCCD) para subscrever (ou anular a subscrição) de notificações e/ou indicações.
- notify
Ativa notificações.
- indicate
Ativa indicações.
- descriptor(uuid: bluetooth.UUID, timeout_ms: int = 2000) Awaitable[ClientDescriptor | None]¶
Assíncrono. Descobre um único descritor por UUID, ou
Nonese não for encontrado.
- descriptors(timeout_ms: int = 2000) ClientDiscover¶
Devolve um iterador assíncrono de objetos
ClientDescriptor. Use comasync fore execute o ciclo até à conclusão.
- class aioble.ClientDescriptor¶
Um descritor GATT remoto descoberto num par. Herda
readewritedeClientCharacteristic.Não construir diretamente.
- characteristic¶
A
ClientCharacteristicproprietária.
- uuid¶
O UUID do descritor.
- class aioble.L2CAPChannel¶
Um canal L2CAP orientado à ligação ativo. Devolvido por
DeviceConnection.l2cap_accept()ouDeviceConnection.l2cap_connect(). Suporta utilização como gestor de contextoasync withque desliga automaticamente ao sair.Não construir diretamente.
- our_mtu¶
Tamanho máximo, em bytes, que o par pode enviar para nós numa única SDU.
- peer_mtu¶
Tamanho máximo, em bytes, que podemos enviar para o par numa única SDU.
- available() bool¶
Devolve de forma síncrona
Truese houver dados de receção em buffer prontos (ou seja,recvintonão vai bloquear).
- recvinto(buf: bytearray, timeout_ms: int | None = None) Awaitable[int]¶
Assíncrono. Recebe para buf, devolvendo o número de bytes lidos. Aguarda novos dados se o canal estiver vazio.
- buf
Buffer pré-alocado a preencher.
- timeout_ms
Tempo máximo a aguardar.
Noneaguarda indefinidamente.
- send(buf: bytes, timeout_ms: int | None = None, chunk_size: int | None = None) Awaitable[None]¶
Assíncrono. Envia buf pelo canal, fragmentando payloads maiores em blocos de tamanho MTU. Aguarda créditos de controlo de fluxo conforme necessário.
- buf
Objeto semelhante a bytes a enviar.
- timeout_ms
Tempo máximo a aguardar por bloco.
- chunk_size
Substituição opcional para o tamanho do bloco por chamada. Limitado a
min(our_mtu * 2, peer_mtu).
- flush(timeout_ms: int | None = None) Awaitable[None]¶
Assíncrono. Aguarda até que qualquer
sendparalisado seja drenado pelo controlador.- timeout_ms
Tempo máximo a aguardar.