bluetooth — Low-Level-Bluetooth

Dieses Modul bietet eine Schnittstelle zum integrierten Bluetooth-Controller. Es unterstützt Bluetooth Low Energy (BLE) in den Rollen Central, Peripheral, Broadcaster und Observer sowie GATT-Server und -Client und verbindungsorientierte L2CAP-Kanäle. Ein Gerät kann gleichzeitig in mehreren Rollen agieren. Pairing und Bonding werden ebenfalls unterstützt.

Diese API ist darauf ausgelegt, dem Low-Level-Bluetooth-Protokoll zu entsprechen, und stellt Bausteine für höhere Abstraktionen wie bestimmte Gerätetypen bereit.

Tipp

Für die meisten Anwendungen ist die höherstufige Bibliothek aioble vorzuziehen, die einen asyncio-basierten Wrapper um dieses Modul bereitstellt. Siehe aioble — Async BLE.

class BLE

class bluetooth.BLE

Gibt das BLE-Singleton-Objekt zurück.

Konfiguration

active(active: bool | None = None, /) bool

Ändert optional den aktiven Zustand des BLE-Funkmoduls und gibt den aktuellen Zustand zurück.

Das Funkmodul muss aktiviert werden, bevor andere Methoden dieser Klasse verwendet werden können.

config(param: str, /) Any
config(*, **kwargs: Any) None

Liest oder setzt Konfigurationswerte der BLE-Schnittstelle. Um einen Wert abzufragen, sollte der Parametername als String in Anführungszeichen angegeben werden, und es wird jeweils nur ein Parameter abgefragt. Zum Setzen von Werten wird die Keyword-Syntax verwendet, wobei ein oder mehrere Parameter gleichzeitig gesetzt werden können.

Aktuell werden folgende Werte unterstützt:

  • 'mac': Die aktuell verwendete Adresse, abhängig vom aktuellen Adressmodus. Dies gibt ein Tupel (addr_type, addr) zurück.

    Siehe gap_scan für Details zum Adresstyp.

    Dies kann nur abgefragt werden, während die Schnittstelle gerade aktiv ist.

  • 'addr_mode': Setzt den Adressmodus. Die Werte sind:

    Wert

    Name

    Verhalten

    0x00

    PUBLIC

    Verwendet die öffentliche Adresse des Controllers.

    0x01

    RANDOM

    Verwendet eine generierte statische Adresse.

    0x02

    RPA

    Verwendet auflösbare private Adressen.

    0x03

    NRPA

    Verwendet nicht-auflösbare private Adressen.

    Standardmäßig verwendet die Schnittstelle eine PUBLIC-Adresse, sofern verfügbar, andernfalls eine RANDOM-Adresse.

  • 'gap_name': Liest/setzt den GAP-Gerätenamen, der vom Generic-Access-Dienst (UUID 0x1800), Characteristic „Device Name“ (UUID 0x2a00) verwendet wird. Dies kann jederzeit gesetzt und mehrfach geändert werden.

  • 'rxbuf': Liest/setzt die Größe des internen Puffers in Byte, der zum Speichern eingehender Ereignisse verwendet wird. Dieser Puffer ist global für den gesamten BLE-Treiber und verarbeitet daher eingehende Daten für alle Ereignisse, einschließlich aller Characteristics. Eine Erhöhung ermöglicht eine bessere Verarbeitung stoßweise eingehender Daten (z. B. Scan-Ergebnisse) sowie den Empfang größerer Characteristic-Werte.

  • 'mtu': Liest/setzt die MTU, die während eines ATT-MTU-Austauschs verwendet wird. Die resultierende MTU ist das Minimum aus diesem Wert und der MTU des entfernten Geräts. Der ATT-MTU-Austausch erfolgt nicht automatisch (es sei denn, das entfernte Gerät initiiert ihn) und muss manuell mit gattc_exchange_mtu ausgelöst werden. Verwenden Sie das Ereignis _IRQ_MTU_EXCHANGED, um die MTU für eine bestimmte Verbindung zu ermitteln.

  • 'bond': Legt fest, ob Bonding während des Pairings aktiviert wird. Wenn aktiviert, setzen Pairing-Anfragen das „bond“-Flag, und die Schlüssel werden von beiden Geräten gespeichert.

  • 'mitm': Legt fest, ob MITM-Schutz für das Pairing erforderlich ist.

  • 'io': Legt die I/O-Fähigkeiten dieses Geräts fest.

    Verfügbare Optionen sind:

    Konstante

    Wert

    Fähigkeit

    _IO_CAPABILITY_DISPLAY_ONLY

    0

    Nur Anzeige

    _IO_CAPABILITY_DISPLAY_YESNO

    1

    Anzeige mit Ja/Nein-Eingabe

    _IO_CAPABILITY_KEYBOARD_ONLY

    2

    Nur Tastatur

    _IO_CAPABILITY_NO_INPUT_OUTPUT

    3

    Keine Ein- oder Ausgabe

    _IO_CAPABILITY_KEYBOARD_DISPLAY

    4

    Tastatur und Anzeige

  • 'le_secure': Legt fest, ob „LE Secure“-Pairing erforderlich ist. Standard ist false (d. h. „Legacy Pairing“ wird zugelassen).

Ereignisbehandlung

irq(handler: Callable[[int, Tuple], Any | None], /) None

Registriert ein Callback für Ereignisse vom BLE-Stack. Der handler nimmt zwei Argumente entgegen: event (einer der unten aufgeführten Codes) und data (ein ereignisspezifisches Tupel von Werten).

Hinweis: Als Optimierung zur Vermeidung unnötiger Speicherzuweisungen sind die Einträge addr, adv_data, char_data, notify_data und uuid in den Tupeln schreibgeschützte memoryview-Instanzen, die auf den internen Ringpuffer von bluetooth zeigen, und nur während des Aufrufs der IRQ-Handler-Funktion gültig. Wenn Ihr Programm einen dieser Werte speichern muss, um nach der Rückkehr des IRQ-Handlers darauf zuzugreifen (z. B. durch Speichern in einer Klasseninstanz oder globalen Variable), muss es eine Kopie der Daten anfertigen, entweder mit bytes() oder bluetooth.UUID(), etwa so:

connected_addr = bytes(addr)  # equivalently: adv_data, char_data, or notify_data
matched_uuid = bluetooth.UUID(uuid)

Beispielsweise könnte der IRQ-Handler für ein Scan-Ergebnis die adv_data untersuchen, um zu entscheiden, ob es sich um das richtige Gerät handelt, und erst dann die Adressdaten zur weiteren Verwendung an anderer Stelle im Programm kopieren. Und um Daten innerhalb des IRQ-Handlers auszugeben, wird print(bytes(addr)) benötigt.

Ein Handler verzweigt typischerweise anhand des Ereigniscodes und entpackt das ereignisspezifische Payload-Tupel:

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
        ...

Jeder Ereigniscode, das von ihm gelieferte Payload und eine kurze Beschreibung sind unten aufgeführt. Bei Ereignissen, deren status-Feld erwähnt wird, ist status bei Erfolg 0 und bei Fehler ein implementierungsspezifischer Wert ungleich null.

Konstante

Wert

Ereignis

Payload-Tupel

_IRQ_CENTRAL_CONNECT

1

Ein Central hat sich mit diesem Peripheral verbunden.

(conn_handle, addr_type, addr)

_IRQ_CENTRAL_DISCONNECT

2

Ein Central hat die Verbindung zu diesem Peripheral getrennt.

(conn_handle, addr_type, addr)

_IRQ_GATTS_WRITE

3

Ein verbundener Client hat in eine lokale Characteristic oder einen Deskriptor geschrieben. Verwenden Sie gatts_read, um den neuen Wert abzurufen.

(conn_handle, attr_handle)

_IRQ_GATTS_READ_REQUEST

4

Ein verbundener Client hat einen Lesevorgang ausgelöst. Geben Sie einen Fehlercode ungleich null aus der Tabelle unten zurück, um den Lesevorgang abzulehnen, oder 0 / None, um ihn zu akzeptieren.

(conn_handle, attr_handle)

_IRQ_SCAN_RESULT

5

Ein einzelnes Advertising-Paket wurde während eines aktiven Scans empfangen.

(addr_type, addr, adv_type, rssi, adv_data)

_IRQ_SCAN_DONE

6

Der aktuelle Scan ist beendet, entweder weil die konfigurierte Dauer abgelaufen ist oder weil gap_scan(None) aufgerufen wurde.

()

_IRQ_PERIPHERAL_CONNECT

7

Ein zuvor ausgelöstes gap_connect war erfolgreich.

(conn_handle, addr_type, addr)

_IRQ_PERIPHERAL_DISCONNECT

8

Ein verbundenes Peripheral hat die Verbindung getrennt.

(conn_handle, addr_type, addr)

_IRQ_GATTC_SERVICE_RESULT

9

Ein Dienst wurde von gattc_discover_services gefunden.

(conn_handle, start_handle, end_handle, uuid)

_IRQ_GATTC_SERVICE_DONE

10

Die Dienstermittlung ist abgeschlossen.

(conn_handle, status)

_IRQ_GATTC_CHARACTERISTIC_RESULT

11

Eine Characteristic wurde von gattc_discover_characteristics gefunden.

(conn_handle, end_handle, value_handle, properties, uuid)

_IRQ_GATTC_CHARACTERISTIC_DONE

12

Die Ermittlung der Characteristics ist abgeschlossen.

(conn_handle, status)

_IRQ_GATTC_DESCRIPTOR_RESULT

13

Ein Deskriptor wurde von gattc_discover_descriptors gefunden.

(conn_handle, dsc_handle, uuid)

_IRQ_GATTC_DESCRIPTOR_DONE

14

Die Ermittlung der Deskriptoren ist abgeschlossen.

(conn_handle, status)

_IRQ_GATTC_READ_RESULT

15

Ein zuvor ausgelöstes gattc_read hat Daten zurückgegeben.

(conn_handle, value_handle, char_data)

_IRQ_GATTC_READ_DONE

16

Ein zuvor ausgelöstes gattc_read ist abgeschlossen.

(conn_handle, value_handle, status)

_IRQ_GATTC_WRITE_DONE

17

Ein zuvor ausgelöstes gattc_write wurde bestätigt.

(conn_handle, value_handle, status)

_IRQ_GATTC_NOTIFY

18

Ein entfernter Server hat eine (unbestätigte) Benachrichtigung gesendet.

(conn_handle, value_handle, notify_data)

_IRQ_GATTC_INDICATE

19

Ein entfernter Server hat eine (bestätigte) Indication gesendet.

(conn_handle, value_handle, notify_data)

_IRQ_GATTS_INDICATE_DONE

20

Eine zuvor gesendete Indication wurde vom Client bestätigt (oder es kam zu einer Zeitüberschreitung).

(conn_handle, value_handle, status)

_IRQ_MTU_EXCHANGED

21

Ein ATT-MTU-Austausch wurde abgeschlossen (von einer der beiden Seiten initiiert).

(conn_handle, mtu)

_IRQ_L2CAP_ACCEPT

22

Ein entferntes Gerät hat eine L2CAP-Verbindung auf einem PSM angefordert, auf dem dieses Gerät lauscht. Geben Sie eine ganze Zahl ungleich null zurück, um abzulehnen, oder 0 / None, um zu akzeptieren.

(conn_handle, cid, psm, our_mtu, peer_mtu)

_IRQ_L2CAP_CONNECT

23

Ein L2CAP-Kanal ist nun eingerichtet, entweder durch Annahme einer eingehenden Anfrage oder durch Abschluss eines ausgehenden l2cap_connect.

(conn_handle, cid, psm, our_mtu, peer_mtu)

_IRQ_L2CAP_DISCONNECT

24

Ein L2CAP-Kanal wurde getrennt. status ist 0 bei sauberer Trennung oder ungleich null, wenn ein ausgehender Verbindungsversuch fehlgeschlagen ist.

(conn_handle, cid, psm, status)

_IRQ_L2CAP_RECV

25

Daten sind auf einem L2CAP-Kanal eingetroffen. Rufen Sie l2cap_recvinto auf, um sie zu lesen.

(conn_handle, cid)

_IRQ_L2CAP_SEND_READY

26

Ein vorheriges l2cap_send, das False zurückgegeben hat, wurde geleert, und der Kanal ist wieder bereit. Ein status ungleich null bedeutet, dass der Sendepuffer übergelaufen ist und die Anwendung die Daten erneut senden muss.

(conn_handle, cid, status)

_IRQ_CONNECTION_UPDATE

27

Das entfernte Gerät hat die Verbindungsparameter aktualisiert (Intervall, Latenz, Supervision-Timeout).

(conn_handle, conn_interval, conn_latency, supervision_timeout, status)

_IRQ_ENCRYPTION_UPDATE

28

Der Verschlüsselungsstatus einer Verbindung hat sich geändert, typischerweise nach Abschluss von Pairing oder Bonding.

(conn_handle, encrypted, authenticated, bonded, key_size)

_IRQ_GET_SECRET

29

Der Stack fordert ein gespeichertes Bonding-Secret an. Wenn key None ist, geben Sie den index-ten gespeicherten Wert von sec_type zurück; andernfalls geben Sie den mit dem angegebenen (sec_type, key) verknüpften Wert zurück. Geben Sie None zurück, wenn nichts gespeichert ist.

(sec_type, index, key)

_IRQ_SET_SECRET

30

Der Stack fordert die Anwendung auf, ein Bonding-Secret dauerhaft zu speichern. Geben Sie True zurück, sobald es gespeichert ist.

(sec_type, key, value)

_IRQ_PASSKEY_ACTION

31

Im Rahmen des Pairings ist eine Passkey-Aktion erforderlich. Antworten Sie mit gap_passkey; siehe die Passkey-Aktionstabelle unten für die möglichen Aktionen.

(conn_handle, action, passkey)

Für das Ereignis _IRQ_GATTS_READ_REQUEST sind die verfügbaren Rückgabecodes:

Konstante

Wert

Bedeutung

_GATTS_NO_ERROR

0x00

Lesevorgang akzeptieren.

_GATTS_ERROR_READ_NOT_PERMITTED

0x02

Lesen nicht erlaubt.

_GATTS_ERROR_WRITE_NOT_PERMITTED

0x03

Schreiben nicht erlaubt.

_GATTS_ERROR_INSUFFICIENT_AUTHENTICATION

0x05

Client ist nicht authentifiziert.

_GATTS_ERROR_INSUFFICIENT_AUTHORIZATION

0x08

Client ist nicht autorisiert.

_GATTS_ERROR_INSUFFICIENT_ENCRYPTION

0x0f

Verbindung ist nicht verschlüsselt.

Für das Ereignis _IRQ_PASSKEY_ACTION sind die verfügbaren Aktionen:

Konstante

Wert

Bedeutung

_PASSKEY_ACTION_NONE

0

Keine Aktion erforderlich.

_PASSKEY_ACTION_INPUT

2

Den Benutzer auffordern, den auf dem entfernten Gerät angezeigten Passkey einzugeben.

_PASSKEY_ACTION_DISPLAY

3

Einen 6-stelligen Passkey anzeigen, den das entfernte Gerät eingeben soll.

_PASSKEY_ACTION_NUMERIC_COMPARISON

4

Bestätigen, dass der Passkey mit dem auf dem entfernten Gerät angezeigten übereinstimmt.

Um Platz in der Firmware zu sparen, sind diese Konstanten nicht im bluetooth-Modul enthalten. Fügen Sie die von Ihnen benötigten aus den obigen Listen zu Ihrem Programm hinzu.

Broadcaster-Rolle (Advertiser)

gap_advertise(interval_us: int | None, adv_data: bytes | None = None, *, resp_data: bytes | None = None, connectable: bool = True) None

Startet das Advertising im angegebenen Intervall (in Mikrosekunden). Dieses Intervall wird auf die nächsten 625 µs abgerundet. Um das Advertising zu stoppen, setzen Sie interval_us auf None.

adv_data und resp_data können von jedem Typ sein, der das Buffer-Protokoll implementiert (z. B. bytes, bytearray, str). adv_data ist in allen Broadcasts enthalten, und resp_data wird als Antwort auf einen aktiven Scan gesendet.

Hinweis: Wenn adv_data (oder resp_data) None ist, werden die beim vorherigen Aufruf von gap_advertise übergebenen Daten wiederverwendet. Dadurch kann ein Broadcaster das Advertising mit nur gap_advertise(interval_us) fortsetzen. Um das Advertising-Payload zu löschen, übergeben Sie ein leeres bytes, d. h. b''.

Observer-Rolle (Scanner)

gap_scan(duration_ms: int | None, interval_us: int = 1280000, window_us: int = 11250, active: bool = False, /) None

Führt einen Scan-Vorgang mit der angegebenen Dauer (in Millisekunden) durch.

Um unbegrenzt zu scannen, setzen Sie duration_ms auf 0.

Um das Scannen zu stoppen, setzen Sie duration_ms auf None.

Verwenden Sie interval_us und window_us, um optional den Arbeitszyklus zu konfigurieren. Der Scanner läuft alle interval_us Mikrosekunden für window_us Mikrosekunden über insgesamt duration_ms Millisekunden. Das Standardintervall und -fenster betragen 1,28 Sekunden bzw. 11,25 Millisekunden (Hintergrund-Scannen).

Für jedes Scan-Ergebnis wird das Ereignis _IRQ_SCAN_RESULT mit den Ereignisdaten (addr_type, addr, adv_type, rssi, adv_data) ausgelöst.

addr_type-Werte geben öffentliche oder zufällige Adressen an:

Wert

Name

Bedeutung

0x00

PUBLIC

Öffentliche Geräteadresse.

0x01

RANDOM

Zufällige Adresse (entweder statisch, RPA oder NRPA; der Typ ist in der Adresse selbst codiert).

adv_type-Werte entsprechen der Bluetooth-Spezifikation:

Wert

Name

Bedeutung

0x00

ADV_IND

Verbindbares und scanbares ungerichtetes Advertising.

0x01

ADV_DIRECT_IND

Verbindbares gerichtetes Advertising.

0x02

ADV_SCAN_IND

Scanbares ungerichtetes Advertising.

0x03

ADV_NONCONN_IND

Nicht-verbindbares ungerichtetes Advertising.

0x04

SCAN_RSP

Scan-Antwort.

active kann auf True gesetzt werden, wenn Sie Scan-Antworten in den Ergebnissen empfangen möchten.

Wenn das Scannen gestoppt wird (entweder durch Ablauf der Dauer oder durch explizites Stoppen), wird das Ereignis _IRQ_SCAN_DONE ausgelöst.

Central-Rolle

Ein Central-Gerät kann sich mit Peripherals verbinden, die es über die Observer-Rolle (siehe gap_scan) erkannt hat oder deren Adresse bekannt ist.

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

Verbindet sich mit einem Peripheral.

Siehe gap_scan für Details zu Adresstypen.

Um einen ausstehenden Verbindungsversuch frühzeitig abzubrechen, rufen Sie gap_connect(None) auf.

Bei Erfolg wird das Ereignis _IRQ_PERIPHERAL_CONNECT ausgelöst. Beim Abbruch eines Verbindungsversuchs wird das Ereignis _IRQ_PERIPHERAL_DISCONNECT ausgelöst.

Das Gerät wartet bis zu scan_duration_ms, um ein Advertising-Payload vom Gerät zu empfangen.

Das Verbindungsintervall kann in Mikrosekunden über min_conn_interval_us und/oder max_conn_interval_us konfiguriert werden. Andernfalls wird ein Standardintervall gewählt, typischerweise zwischen 30000 und 50000 Mikrosekunden. Ein kürzeres Intervall erhöht den Durchsatz auf Kosten des Stromverbrauchs.

Peripheral-Rolle

Von einem Peripheral-Gerät wird erwartet, dass es verbindbare Advertisements sendet (siehe gap_advertise). Es agiert üblicherweise als GATT-Server, nachdem es zuvor Dienste und Characteristics mit gatts_register_services registriert hat.

Wenn sich ein Central verbindet, wird das Ereignis _IRQ_CENTRAL_CONNECT ausgelöst.

Central- & Peripheral-Rollen

gap_disconnect(conn_handle: int, /) bool

Trennt das angegebene Verbindungs-Handle. Dies kann entweder ein Central sein, das sich mit diesem Gerät verbunden hat (wenn es als Peripheral agiert), oder ein Peripheral, mit dem sich dieses Gerät zuvor verbunden hat (wenn es als Central agiert).

Bei Erfolg wird das Ereignis _IRQ_PERIPHERAL_DISCONNECT oder _IRQ_CENTRAL_DISCONNECT ausgelöst.

Gibt False zurück, wenn das Verbindungs-Handle nicht verbunden war, andernfalls True.

GATT-Server

Ein GATT-Server verfügt über eine Reihe registrierter Dienste. Jeder Dienst kann Characteristics enthalten, die jeweils einen Wert haben. Characteristics können außerdem Deskriptoren enthalten, die ihrerseits Werte besitzen.

Diese Werte werden lokal gespeichert und über ihr „value handle“ angesprochen, das während der Dienstregistrierung erzeugt wird. Sie können außerdem von einem entfernten Client-Gerät gelesen oder beschrieben werden. Zusätzlich kann ein Server eine Characteristic über ein Verbindungs-Handle an einen verbundenen Client „benachrichtigen“ (notify).

Ein Gerät in der Central- oder Peripheral-Rolle kann als GATT-Server fungieren, in den meisten Fällen ist es jedoch üblicher, dass ein Peripheral-Gerät als Server agiert.

Characteristics und Deskriptoren haben eine standardmäßige Maximalgröße von 20 Byte (die Standard-ATT-MTU von 23 Byte abzüglich eines 3-Byte-ATT-Headers; eine größere ausgehandelte MTU erhöht dieses Limit für sich genommen nicht). Alles, was ein Client in sie schreibt, wird auf diese Länge gekürzt. Jeder lokale Schreibvorgang erhöht jedoch die Maximalgröße. Wenn Sie also größere Schreibvorgänge von einem Client auf eine bestimmte Characteristic zulassen möchten, verwenden Sie gatts_write nach der Registrierung, z. B. gatts_write(char_handle, bytes(100)).

gatts_register_services(services_definition: Sequence[Sequence], /) Sequence[Sequence[int]]

Konfiguriert den Server mit den angegebenen Diensten und ersetzt dabei alle vorhandenen Dienste.

services_definition ist eine Liste von Diensten, wobei jeder Dienst ein zweielementiges Tupel ist, das eine UUID und eine Liste von Characteristics enthält.

Jede Characteristic ist ein zwei- oder dreielementiges Tupel, das eine UUID, einen flags-Wert und optional eine Liste von descriptors enthält.

Jeder Deskriptor ist ein zweielementiges Tupel, das eine UUID und einen flags-Wert enthält.

Die flags sind eine bitweise ODER-Kombination der unten definierten Flags. Sie legen sowohl das Verhalten der Characteristic (oder des Deskriptors) als auch die Sicherheits- und Datenschutzanforderungen fest.

Der Rückgabewert ist eine Liste (ein Element pro Dienst) von Tupeln (jedes Element ist ein value handle). Characteristic- und Deskriptor-Handles werden in dasselbe Tupel zusammengeführt, in der Reihenfolge, in der sie definiert sind.

Das folgende Beispiel registriert zwei Dienste (Heart Rate und 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),
)

Die drei value handles (hr, tx, rx) können mit gatts_read, gatts_write, gatts_notify und gatts_indicate verwendet werden.

Hinweis: Das Advertising muss gestoppt werden, bevor Dienste registriert werden.

Verfügbare Flags für Characteristics und Deskriptoren sind:

Konstante

Wert

Bedeutung

_FLAG_BROADCAST

0x0001

Characteristic darf gebroadcastet werden.

_FLAG_READ

0x0002

Client darf den Wert lesen.

_FLAG_WRITE_NO_RESPONSE

0x0004

Client darf schreiben, ohne eine Antwort zu erwarten.

_FLAG_WRITE

0x0008

Client darf mit bestätigter Antwort schreiben.

_FLAG_NOTIFY

0x0010

Server darf Benachrichtigungen senden (unbestätigt).

_FLAG_INDICATE

0x0020

Server darf Indications senden (bestätigt).

_FLAG_AUTHENTICATED_SIGNED_WRITE

0x0040

Client darf signierte Schreibvorgänge ausführen.

_FLAG_AUX_WRITE

0x0100

Erweiterte Eigenschaften: Warteschlangen-/zuverlässige Schreibvorgänge sind erlaubt.

_FLAG_READ_ENCRYPTED

0x0200

Lesen erfordert eine verschlüsselte Verbindung.

_FLAG_READ_AUTHENTICATED

0x0400

Lesen erfordert eine authentifizierte (MITM-geschützte) Verbindung.

_FLAG_READ_AUTHORIZED

0x0800

Lesen erfordert eine Autorisierung auf Anwendungsebene.

_FLAG_WRITE_ENCRYPTED

0x1000

Schreiben erfordert eine verschlüsselte Verbindung.

_FLAG_WRITE_AUTHENTICATED

0x2000

Schreiben erfordert eine authentifizierte (MITM-geschützte) Verbindung.

_FLAG_WRITE_AUTHORIZED

0x4000

Schreiben erfordert eine Autorisierung auf Anwendungsebene.

Wie bei den Ereigniskonstanten oben werden auch diese Flags nicht vom bluetooth-Modul bereitgestellt; kopieren Sie die von Ihnen benötigten in Ihr Programm.

gatts_read(value_handle: int, /) bytes

Liest den lokalen Wert für dieses Handle (der entweder von gatts_write oder von einem entfernten Client geschrieben wurde).

gatts_write(value_handle: int, data: bytes, send_update: bool = False, /) None

Schreibt den lokalen Wert für dieses Handle, der von einem Client gelesen werden kann.

Wenn send_update True ist, werden alle abonnierten Clients über diesen Schreibvorgang benachrichtigt (notify) oder es wird ihnen eine Indication gesendet (je nachdem, was sie abonniert haben und welche Operationen die Characteristic unterstützt).

gatts_notify(conn_handle: int, value_handle: int, data: bytes | None = None, /) None

Sendet eine Benachrichtigungsanfrage an einen verbundenen Client.

Wenn data None ist (Standard), wird der aktuelle lokale Wert (wie mit gatts_write gesetzt) gesendet.

Andernfalls, wenn data nicht None ist, wird dieser Wert als Teil der Benachrichtigung an den Client gesendet. Der lokale Wert wird nicht verändert.

Hinweis: Die Benachrichtigung wird unabhängig vom Abonnementstatus des Clients für diese Characteristic gesendet.

gatts_indicate(conn_handle: int, value_handle: int, data: bytes | None = None, /) None

Sendet eine Indication-Anfrage an einen verbundenen Client.

Wenn data None ist (Standard), wird der aktuelle lokale Wert (wie mit gatts_write gesetzt) gesendet.

Andernfalls, wenn data nicht None ist, wird dieser Wert als Teil der Indication an den Client gesendet. Der lokale Wert wird nicht verändert.

Bei Bestätigung (oder Fehler, z. B. Zeitüberschreitung) wird das Ereignis _IRQ_GATTS_INDICATE_DONE ausgelöst.

Hinweis: Die Indication wird unabhängig vom Abonnementstatus des Clients für diese Characteristic gesendet.

gatts_set_buffer(value_handle: int, len: int, append: bool = False, /) None

Setzt die interne Puffergröße für einen Wert in Byte. Dies begrenzt den größtmöglichen empfangbaren Schreibvorgang. Der Standard ist 20 Byte (Standard-ATT-MTU von 23 abzüglich des 3-Byte-ATT-Headers).

Wenn append auf True gesetzt wird, hängen alle entfernten Schreibvorgänge an den aktuellen Wert an, anstatt ihn zu ersetzen. Auf diese Weise können höchstens len Byte gepuffert werden. Wenn Sie gatts_read verwenden, wird der Wert nach dem Lesen gelöscht. Diese Funktion ist nützlich, wenn man etwas wie den Nordic UART Service implementiert.

GATT-Client

Ein GATT-Client kann Characteristics auf einem entfernten GATT-Server ermitteln sowie lesen/schreiben.

Es ist üblicher, dass ein Gerät in der Central-Rolle als GATT-Client agiert, es ist jedoch auch möglich, dass ein Peripheral als Client agiert, um Informationen über das verbundene Central zu ermitteln (z. B. um den Gerätenamen aus dem Device-Information-Dienst zu lesen).

gattc_discover_services(conn_handle: int, uuid: UUID | None = None, /) None

Fragt einen verbundenen Server nach seinen Diensten ab.

Geben Sie optional eine Dienst-uuid an, um nur diesen Dienst abzufragen.

Für jeden ermittelten Dienst wird das Ereignis _IRQ_GATTC_SERVICE_RESULT ausgelöst, gefolgt von _IRQ_GATTC_SERVICE_DONE bei Abschluss.

gattc_discover_characteristics(conn_handle: int, start_handle: int, end_handle: int, uuid: UUID | None = None, /) None

Fragt einen verbundenen Server nach Characteristics im angegebenen Bereich ab.

Geben Sie optional eine Characteristic-uuid an, um nur diese Characteristic abzufragen.

Die Übergabe von start_handle=1 und end_handle=0xffff deckt den gesamten Bereich der GATT-Attribut-Handles ab, sodass diese Kombination effektiv jeden Dienst auf dem entfernten Gerät durchsucht.

Für jede ermittelte Characteristic wird das Ereignis _IRQ_GATTC_CHARACTERISTIC_RESULT ausgelöst, gefolgt von _IRQ_GATTC_CHARACTERISTIC_DONE bei Abschluss.

gattc_discover_descriptors(conn_handle: int, start_handle: int, end_handle: int, /) None

Fragt einen verbundenen Server nach Deskriptoren im angegebenen Bereich ab.

Für jeden ermittelten Deskriptor wird das Ereignis _IRQ_GATTC_DESCRIPTOR_RESULT ausgelöst, gefolgt von _IRQ_GATTC_DESCRIPTOR_DONE bei Abschluss.

gattc_read(conn_handle: int, value_handle: int, /) None

Löst einen entfernten Lesevorgang an einen verbundenen Server für das angegebene Characteristic- oder Deskriptor-Handle aus.

Wenn ein Wert verfügbar ist, wird das Ereignis _IRQ_GATTC_READ_RESULT ausgelöst, gefolgt von _IRQ_GATTC_READ_DONE bei Abschluss.

gattc_write(conn_handle: int, value_handle: int, data: bytes, mode: int = 0, /) None

Löst einen entfernten Schreibvorgang an einen verbundenen Server für das angegebene Characteristic- oder Deskriptor-Handle aus.

Das Argument mode gibt das Schreibverhalten an, wobei aktuell folgende Werte unterstützt werden:

  • mode=0 (Standard) ist ein Schreibvorgang ohne Antwort: Der Schreibvorgang wird an den entfernten Server gesendet, es wird jedoch keine Bestätigung zurückgegeben und kein Ereignis ausgelöst.

  • mode=1 ist ein Schreibvorgang mit Antwort: Der entfernte Server wird aufgefordert, eine Antwort/Bestätigung zu senden, dass er die Daten empfangen hat.

Wenn eine Antwort vom entfernten Server empfangen wird, wird das Ereignis _IRQ_GATTC_WRITE_DONE ausgelöst.

gattc_exchange_mtu(conn_handle: int, /) None

Initiiert einen MTU-Austausch mit einem verbundenen Server unter Verwendung der bevorzugten MTU, die mit BLE.config(mtu=value) gesetzt wurde.

Das Ereignis _IRQ_MTU_EXCHANGED wird ausgelöst, wenn der MTU-Austausch abgeschlossen ist.

Der MTU-Austausch wird typischerweise vom Central initiiert; NimBLE unterstützt beide Rollen.

Verbindungsorientierte L2CAP-Kanäle

Diese Funktion ermöglicht einen socketähnlichen Datenaustausch zwischen zwei BLE-Geräten. Sobald die Geräte über GAP verbunden sind, kann jedes Gerät auf einem numerischen PSM (Protocol/Service Multiplexer) auf eine Verbindung des anderen lauschen.

Es kann jeweils nur ein L2CAP-Kanal aktiv sein (d. h. Sie können sich nicht verbinden, während Sie lauschen).

Aktive L2CAP-Kanäle werden durch das Verbindungs-Handle, auf dem sie eingerichtet wurden, und eine CID (Channel ID) identifiziert.

Verbindungsorientierte Kanäle verfügen über eine integrierte kreditbasierte Flusssteuerung. Anders als bei ATT, wo Geräte eine gemeinsame MTU aushandeln, setzen sowohl das lauschende als auch das verbindende Gerät jeweils eine unabhängige MTU, die die maximale Menge ausstehender Daten begrenzt, die das entfernte Gerät senden kann, bevor sie in l2cap_recvinto vollständig verarbeitet werden.

l2cap_listen(psm: int, mtu: int, /) None

Beginnt, auf dem angegebenen psm auf eingehende L2CAP-Kanalanfragen zu lauschen, wobei die lokale MTU auf mtu gesetzt wird.

Wenn ein entferntes Gerät eine Verbindung initiiert, wird das Ereignis _IRQ_L2CAP_ACCEPT ausgelöst, was dem lauschenden Server die Möglichkeit gibt, die eingehende Verbindung abzulehnen (durch Rückgabe einer ganzen Zahl ungleich null).

Sobald die Verbindung akzeptiert ist, wird das Ereignis _IRQ_L2CAP_CONNECT ausgelöst, wodurch der Server die Channel ID (CID) sowie die lokale und entfernte MTU erhalten kann.

Hinweis: Es ist derzeit nicht möglich, das Lauschen zu stoppen.

l2cap_connect(conn_handle: int, psm: int, mtu: int, /) None

Verbindet sich mit einem lauschenden Peer auf dem angegebenen psm, wobei die lokale MTU auf mtu gesetzt wird.

Bei erfolgreicher Verbindung wird das Ereignis _IRQ_L2CAP_CONNECT ausgelöst, wodurch der Client die CID sowie die lokale und entfernte (Peer-)MTU erhalten kann.

Eine erfolglose Verbindung löst das Ereignis _IRQ_L2CAP_DISCONNECT mit einem Status ungleich null aus.

l2cap_disconnect(conn_handle: int, cid: int, /) None

Trennt einen aktiven L2CAP-Kanal mit dem angegebenen conn_handle und cid.

l2cap_send(conn_handle: int, cid: int, buf: bytes, /) bool

Sendet den angegebenen buf (der das Buffer-Protokoll unterstützen muss) auf dem durch conn_handle und cid identifizierten L2CAP-Kanal.

Der Puffer muss beide Limits erfüllen: Er darf die entfernte (Peer-)MTU nicht überschreiten und darf das Doppelte der lokalen MTU nicht überschreiten.

Dies gibt False zurück, wenn der Kanal nun „blockiert“ ist, was bedeutet, dass l2cap_send nicht erneut aufgerufen werden darf, bis das Ereignis _IRQ_L2CAP_SEND_READY empfangen wurde (was geschieht, wenn das entfernte Gerät mehr Credits gewährt, typischerweise nachdem es die Daten empfangen und verarbeitet hat).

l2cap_recvinto(conn_handle: int, cid: int, buf: Any | None, /) int

Empfängt Daten vom angegebenen conn_handle und cid in den bereitgestellten buf (der das Buffer-Protokoll unterstützen muss, z. B. bytearray oder memoryview).

Gibt die Anzahl der vom Kanal gelesenen Bytes zurück.

Wenn buf None ist, wird die Anzahl der verfügbaren Bytes zurückgegeben.

Hinweis: Nach dem Empfang des Ereignisses _IRQ_L2CAP_RECV sollte die Anwendung weiterhin l2cap_recvinto aufrufen, bis keine weiteren Bytes mehr im Empfangspuffer verfügbar sind (typischerweise bis zur Größe der entfernten (Peer-)MTU).

Bis der Empfangspuffer leer ist, werden dem entfernten Gerät keine weiteren Kanal-Credits gewährt, und es kann keine weiteren Daten senden.

Pairing und Bonding

Pairing ermöglicht es, eine Verbindung durch den Austausch von Secrets zu verschlüsseln und zu authentifizieren (mit optionalem MITM-Schutz durch Passkey-Authentifizierung).

Bonding ist der Vorgang, diese Secrets in nichtflüchtigem Speicher abzulegen. Wenn ein Gerät gebondet ist, kann es eine auflösbare private Adresse (RPA) eines anderen Geräts anhand des gespeicherten Identity Resolving Key (IRK) auflösen. Um Bonding zu unterstützen, muss eine Anwendung die Ereignisse _IRQ_GET_SECRET und _IRQ_SET_SECRET implementieren.

gap_pair(conn_handle: int, /) None

Initiiert das Pairing mit dem entfernten Gerät.

Stellen Sie vor dem Aufruf sicher, dass die Konfigurationsoptionen io, mitm, le_secure und bond gesetzt sind (über config).

Bei erfolgreichem Pairing wird das Ereignis _IRQ_ENCRYPTION_UPDATE ausgelöst.

gap_passkey(conn_handle: int, action: int, passkey: int, /) None

Antwortet auf ein _IRQ_PASSKEY_ACTION-Ereignis für das angegebene conn_handle und action. Die Bedeutung von passkey hängt von action ab (was wiederum von der konfigurierten I/O-Fähigkeit abhängt):

Aktion

Erforderliche passkey-Antwort

_PASSKEY_ACTION_INPUT

Der Passkey, den der Benutzer vom entfernten Gerät abliest.

_PASSKEY_ACTION_DISPLAY

Ein lokal generierter zufälliger 6-stelliger Passkey, der dem Benutzer angezeigt wird.

_PASSKEY_ACTION_NUMERIC_COMPARISON

1, um den im _IRQ_PASSKEY_ACTION-Ereignis angezeigten Passkey zu akzeptieren, oder 0, um das Pairing abzubrechen.

class UUID

class bluetooth.UUID(value: int | bytes | str, /)

Erstellt eine UUID-Instanz mit dem angegebenen value. Bluetooth verwendet drei UUID-Breiten; UUID akzeptiert jede davon:

UUID-Breite

Akzeptierte value-Typen

Beispiel

16-Bit

int oder ein 2-Byte-Puffer (Little-Endian)

UUID(0x2908) oder UUID(b'\x08\x29')

32-Bit

4-Byte-Puffer (Little-Endian)

UUID(b'\x08\x29\x00\x00')

128-Bit

16-Byte-Puffer oder ein mit Bindestrichen versehener String

UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')

16- und 32-Bit-UUIDs sind typischerweise SIG-zugewiesene Bezeichner (siehe die zugewiesenen Bluetooth-Nummern); 128-Bit-UUIDs sind normalerweise herstellerdefiniert.