====== std.hardware.bluetooth ====== Nativer Bluetooth-Stack für Linux: von rohen AF_BLUETOOTH-Sockets über BlueZ-D-Bus-Steuerung bis zu vollständigen GATT-Client-/Server-Implementierungen für Bluetooth Low Energy (BLE) und Classic Bluetooth (RFCOMM). Alle neun Units implementieren das Protokoll direkt in Lyx — keine externen Bluetooth-Bibliotheken. Verbindungen werden als Dateideskriptoren (''int64'') verwaltet; jede Funktion nimmt einen ''fd'' entgegen. → [[lyx_-_programmiersprache:units|Standard Library]] · [[lyx_-_programmiersprache:units:android|std.android]] ---- ===== Architektur ===== Übersicht der internen Schichten und Abhängigkeiten: ┌─────────────────────────────────────────────────────┐ │ AI / Profile-Typen │ │ bluetooth_ai │ ├─────────────────────────────────────────────────────┤ │ BLE: GATT-Schicht │ │ bluetooth_gattc · bluetooth_gatts │ ├──────────────────────────┬──────────────────────────┤ │ BLE: L2CAP / ATT │ Classic: RFCOMM │ │ bluetooth_l2cap │ bluetooth_rfcomm │ ├──────────────────────────┴──────────────────────────┤ │ Erweiterungen (BLE Scanner, Advertising, Mesh) │ │ bluetooth_ext │ ├─────────────────────────────────────────────────────┤ │ Steuerungsebene (BlueZ D-Bus) │ │ bluetooth_dbus │ ├─────────────────────────────────────────────────────┤ │ Typen & Low-Level Syscalls │ │ bluetooth_types · bluetooth │ └─────────────────────────────────────────────────────┘ ---- ===== Units ===== ^ Unit ^ Beschreibung ^ | [[lyx_-_programmiersprache:units:hardware:bluetooth|std.hardware.bluetooth]] | Low-Level Bluetooth-Socket-Syscalls (AF_BLUETOOTH): BTSocket, BTConnect, BTSend, BTRecv, BTIoctl | | [[lyx_-_programmiersprache:units:hardware:bluetooth_types|std.hardware.bluetooth_types]] | Adress-Typen und -Hilfsfunktionen: BTAddrFromBytes, BTAddrToStr, BTSockAddrRcCreate, BTSockAddrL2Create | | [[lyx_-_programmiersprache:units:hardware:bluetooth_dbus|std.hardware.bluetooth_dbus]] | BlueZ D-Bus Steuerungsebene: BlueZOpenConnection, BlueZDiscoverDevices, BlueZConnectDevice | | [[lyx_-_programmiersprache:units:hardware:bluetooth_rfcomm|std.hardware.bluetooth_rfcomm]] | RFCOMM (Classic Bluetooth Serial): RFCommConnect, RFCommListen, RFCommSend, RFCommRecv | | [[lyx_-_programmiersprache:units:hardware:bluetooth_l2cap|std.hardware.bluetooth_l2cap]] | L2CAP + ATT-Protokollschicht: L2CapConnect, AttReadChar, AttWriteChar, AttRecvNotification | | [[lyx_-_programmiersprache:units:hardware:bluetooth_gattc|std.hardware.bluetooth_gattc]] | GATT-Client: GattDiscoverServices, GattDiscoverChars, GattReadChar, GattWriteChar, GattEnableNotification | | [[lyx_-_programmiersprache:units:hardware:bluetooth_gatts|std.hardware.bluetooth_gatts]] | GATT-Server: GattServerRegister, GattServerHandleNext, GattServerSendNotification | | [[lyx_-_programmiersprache:units:hardware:bluetooth_ext|std.hardware.bluetooth_ext]] | BLE Scanner, Advertising und Mesh: BleScannerStart, BleAdvertisementRegister, MeshNetworkJoin | | [[lyx_-_programmiersprache:units:hardware:bluetooth_ai|std.hardware.bluetooth_ai]] | KI-native, typsichere Bluetooth-Profile als Compiler-Typen | ---- ===== std.hardware.bluetooth ===== Unterste Schicht: direkte AF_BLUETOOTH-Socket-Syscalls. Wird in der Regel nicht direkt verwendet — ''bluetooth_rfcomm'' und ''bluetooth_l2cap'' bauen darauf auf. ==== Protokoll-Konstanten ==== ^ Konstante ^ Wert ^ Beschreibung ^ | ''AF_BLUETOOTH'' | 31 | Socket-Family für Bluetooth | | ''BTPROTO_L2CAP'' | 0 | L2CAP-Protokoll (BLE und Classic) | | ''BTPROTO_HCI'' | 1 | Host Controller Interface (raw) | | ''BTPROTO_RFCOMM'' | 3 | RFCOMM: serielle Emulation (Classic) | | ''BTPROTO_BNEP'' | 4 | Bluetooth Network Encapsulation | | ''BTPROTO_SCO'' | 6 | Synchronous Connection-Oriented (Audio) | | ''BT_PSM_ATT'' | 31 | ATT-Protokoll-PSM (0x001F) | | ''SOCK_SEQPACKET'' | 5 | Paket-orientierter Socket (L2CAP BLE) | ==== Security-Flags (BT_LM_*) ==== ^ Konstante ^ Beschreibung ^ | ''BT_LM_AUTH'' | Authentifizierung erforderlich | | ''BT_LM_ENCRYPT'' | Verschlüsselung erforderlich | | ''BT_LM_SECURE'' | Secure Simple Pairing erzwingen | ==== Funktionen ==== ^ Signatur ^ Beschreibung ^ | ''BTSocket(socktype: int64, protocol: int64): int64'' | Erzeugt AF_BLUETOOTH-Socket; gibt fd zurück | | ''BTBind(fd: int64, addrPtr: int64, addrLen: int64): int64'' | Bindet Socket an lokale Adresse | | ''BTConnect(fd: int64, addrPtr: int64, addrLen: int64): int64'' | Verbindet zum Remote-Gerät | | ''BTListen(fd: int64, backlog: int64): int64'' | Öffnet Socket als Server | | ''BTAccept(fd: int64, addrPtr: int64, addrLenPtr: int64): int64'' | Nimmt eingehende Verbindung an | | ''BTSend(fd: int64, buf: int64, len: int64, flags: int64): int64'' | Sendet Daten | | ''BTRecv(fd: int64, buf: int64, len: int64, flags: int64): int64'' | Empfängt Daten | | ''BTGetSockOpt(fd: int64, level: int64, optname: int64, optval: int64, optlen: int64): int64'' | Liest Socket-Option | | ''BTSetSockOpt(fd: int64, level: int64, optname: int64, optval: int64, optlen: int64): int64'' | Setzt Socket-Option | | ''BTSocketPoll(fdsPtr: int64, nfds: int64, timeoutMs: int64): int64'' | ''poll()'' über mehrere BT-Sockets | | ''BTIoctl(fd: int64, request: int64, argPtr: int64): int64'' | HCI-ioctl (HCIDEVUP, HCIGETDEVINFO …) | | ''BTClose(fd: int64): int64'' | Schließt Socket | | ''BTPollFdSet(ptr: int64, fd: int64, events: int64)'' | Befüllt pollfd-Eintrag in einem Array | | ''BTPollFdRevents(ptr: int64): int64'' | Liest revents aus einem pollfd-Eintrag | ---- ===== std.hardware.bluetooth_types ===== Adress-Typen und Hilfsfunktionen. Alle Bluetooth-Adressen sind heap-allozierte 6-Byte-Puffer (''int64'' als Zeiger). ==== Größen-Konstanten ==== ^ Konstante ^ Wert ^ Beschreibung ^ | ''BT_BDADDR_SIZE'' | 6 | Größe einer Bluetooth-MAC-Adresse in Bytes | | ''BT_SOCKADDR_RC_SIZE'' | 10 | Größe von ''struct sockaddr_rc'' (RFCOMM) | | ''BT_SOCKADDR_L2_SIZE'' | 14 | Größe von ''struct sockaddr_l2'' (L2CAP) | | ''BDADDR_BREDR'' | 0 | Klassisches Bluetooth (BR/EDR) | | ''BDADDR_LE_PUBLIC'' | 1 | BLE — öffentliche Adresse | | ''BDADDR_LE_RANDOM'' | 2 | BLE — zufällige Adresse | ==== Funktionen ==== ^ Signatur ^ Beschreibung ^ | ''BTAddrFromBytes(b0..b5: int64): int64'' | Erzeugt Adress-Puffer aus 6 einzelnen Bytes; gibt Zeiger zurück | | ''BTAddrGetByte(addr: int64, byteIdx: int64): int64'' | Liest ein Adress-Byte (Index 0–5) | | ''BTAddrToUInt64(addr: int64): int64'' | Gibt Adresse als uint64 zurück | | ''BTAddrToStr(addr: int64, outBuf: int64)'' | Schreibt ''AA:BB:CC:DD:EE:FF''-String nach outBuf (min. 18 Bytes) | | ''BTStrToAddr(s: int64): int64'' | Parst ''AA:BB:CC:DD:EE:FF''-String; gibt Adress-Zeiger zurück | | ''BTSockAddrRcCreate(buf: int64, bdaddr: int64, channel: int64)'' | Füllt ''struct sockaddr_rc'' für RFCOMM | | ''BTSockAddrL2Create(buf: int64, psm: int64, bdaddr: int64, addrType: int64)'' | Füllt ''struct sockaddr_l2'' für L2CAP | | ''BTSockAddrRcReadAddr(buf: int64): int64'' | Liest bdaddr aus sockaddr_rc | | ''BTSockAddrRcReadChannel(buf: int64): int64'' | Liest channel aus sockaddr_rc | import std.hardware.bluetooth_types; import std.alloc; var addr := BTStrToAddr("AA:BB:CC:DD:EE:FF"); var outBuf: int64 := alloc(18); BTAddrToStr(addr, outBuf); // → "AA:BB:CC:DD:EE:FF" ---- ===== std.hardware.bluetooth_dbus ===== Steuerungsebene über das BlueZ-D-Bus-Interface. Ermöglicht Gerätesuche, Pairing und Verbindungsaufbau ohne direkten HCI-Zugriff. Erfordert einen laufenden BlueZ-Daemon (''bluetoothd''). ==== Wichtige Konstanten ==== ^ Konstante ^ Beschreibung ^ | ''DBUS_TYPE_METHOD_CALL'' | Nachrichtentyp: Methodenaufruf | | ''DBUS_HDR_PATH'' | Header-Feld: Objekt-Pfad | | ''DBUS_HDR_INTERFACE'' | Header-Feld: Interface-Name | | ''DBUS_HDR_MEMBER'' | Header-Feld: Methoden-/Signal-Name | | ''DBUS_HDR_DESTINATION'' | Header-Feld: Ziel-Bus-Name | ==== Funktionen ==== ^ Signatur ^ Beschreibung ^ | ''BlueZOpenConnection(): int64'' | Öffnet Unix-Domain-Socket zum BlueZ-Daemon; gibt fd zurück | | ''BlueZClose(fd: int64)'' | Schließt D-Bus-Verbindung | | ''BlueZStartDiscovery(fd: int64, adapterPath: int64, pathLen: int64): int64'' | Startet Gerätescan auf dem Adapter (z. B. ''/org/bluez/hci0'') | | ''BlueZStopDiscovery(fd: int64, adapterPath: int64, pathLen: int64): int64'' | Stoppt den Scan | | ''BlueZGetManagedObjects(fd: int64, outBuf: int64, maxLen: int64): int64'' | Liest alle bekannten Geräte und deren Properties | | ''BlueZFindDeviceAddress(data: int64, dataLen: int64, addrBuf: int64): int64'' | Sucht Geräteadresse in GetManagedObjects-Antwort | | ''BlueZDiscoverDevices(fd: int64, adapterPath: int64, pathLen: int64, ...): int64'' | Kombinierter Scan-Helfer: startet, wartet, liest Geräteliste | | ''BlueZPairDevice(fd: int64, devicePath: int64, pathLen: int64): int64'' | Startet Pairing-Prozess mit einem Gerät | | ''BlueZConnectDevice(fd: int64, devicePath: int64, pathLen: int64): int64'' | Verbindet mit einem bekannten Gerät | | ''BlueZDisconnectDevice(fd: int64, devicePath: int64, pathLen: int64): int64'' | Trennt Verbindung | import std.hardware.bluetooth_dbus; import std.hardware.bluetooth_types; import std.alloc; import std.io; fn ScanDevices(): void { var fd := BlueZOpenConnection(); var adapterPath: pchar := "/org/bluez/hci0"; var pathLen: int64 := 16; BlueZStartDiscovery(fd, adapterPath, pathLen); Sleep(5000); BlueZStopDiscovery(fd, adapterPath, pathLen); var buf: int64 := alloc(4096); BlueZGetManagedObjects(fd, buf, 4096); var addrBuf: int64 := alloc(18); BlueZFindDeviceAddress(buf, 4096, addrBuf); Print(addrBuf); BlueZClose(fd); free(buf, 4096); free(addrBuf, 18); } ---- ===== std.hardware.bluetooth_rfcomm ===== RFCOMM emuliert einen seriellen Port über Bluetooth Classic (BR/EDR). Typische Anwendungen: Verbindung zu Mikrocontrollern (HC-05, HC-06), Barcode-Scannern und Legacy-Geräten. ==== Funktionen ==== ^ Signatur ^ Beschreibung ^ | ''RFCommConnect(bdaddr: int64, channel: int64): int64'' | Verbindet als Client; gibt fd zurück | | ''RFCommListen(channel: int64, backlog: int64): int64'' | Öffnet Server-Socket | | ''RFCommAccept(listenFd: int64, remoteAddrOut: int64): int64'' | Nimmt Verbindung an; füllt remoteAddrOut | | ''RFCommSend(fd: int64, buf: int64, len: int64): int64'' | Sendet Daten | | ''RFCommSendAll(fd: int64, buf: int64, len: int64): int64'' | Sendet alle Daten (loop bis len Bytes gesendet) | | ''RFCommRecv(fd: int64, buf: int64, len: int64): int64'' | Empfängt Daten | | ''RFCommSetSecurity(fd: int64, flags: int64): int64'' | Setzt Sicherheitsstufe (BT_LM_AUTH, BT_LM_ENCRYPT …) | | ''RFCommPoll(fd: int64, timeoutMs: int64): int64'' | Wartet auf eingehende Daten (> 0 = Daten verfügbar) | | ''RFCommClose(fd: int64): int64'' | Schließt Verbindung | import std.hardware.bluetooth_rfcomm; import std.hardware.bluetooth_types; import std.alloc; import std.io; fn ConnectArduino(): void { var addr := BTStrToAddr("98:D3:31:F5:AB:CD"); var fd := RFCommConnect(addr, 1); var msg: pchar := "LED:ON\n"; RFCommSendAll(fd, msg, 7); var buf: int64 := alloc(64); var n := RFCommRecv(fd, buf, 63); Print(buf); RFCommClose(fd); free(buf, 64); } ---- ===== std.hardware.bluetooth_l2cap ===== L2CAP ist die Transportschicht für BLE-Verbindungen. Diese Unit enthält zusätzlich eine vollständige ATT-Implementierung (Attribute Protocol) — die Grundlage für GATT. ==== L2CAP-Funktionen ==== ^ Signatur ^ Beschreibung ^ | ''L2CapConnect(bdaddr: int64, psm: int64, addrType: int64): int64'' | Verbindet L2CAP-Socket; addrType: BDADDR_LE_PUBLIC / BDADDR_LE_RANDOM | | ''L2CapListen(psm: int64, backlog: int64): int64'' | Öffnet Server-Socket | | ''L2CapSetMtu(fd: int64, imtu: int64): int64'' | Setzt Input-MTU | | ''L2CapClose(fd: int64): int64'' | Schließt Verbindung | | ''L2CapPoll(fd: int64, timeoutMs: int64): int64'' | Wartet auf eingehende Daten | ==== ATT-Funktionen ==== ^ Signatur ^ Beschreibung ^ | ''AttExchangeMtu(fd: int64, clientMtu: int64): int64'' | MTU-Verhandlung; gibt Server-MTU zurück | | ''AttSend(fd: int64, opcode: int64, payload: int64, payloadLen: int64): int64'' | Sendet rohe ATT-PDU | | ''AttRecv(fd: int64, opcodeOut: int64, dataBuf: int64, bufLen: int64): int64'' | Empfängt ATT-PDU; schreibt Opcode nach opcodeOut | | ''AttReadChar(fd: int64, handle: int64, dataBuf: int64, bufLen: int64): int64'' | Liest Attribut per Handle (ATT_OP_READ_REQ) | | ''AttWriteChar(fd: int64, handle: int64, data: int64, dataLen: int64): int64'' | Schreibt Attribut mit Antwort (ATT_OP_WRITE_REQ) | | ''AttWriteCmd(fd: int64, handle: int64, data: int64, dataLen: int64): int64'' | Schreibt ohne Antwort (ATT_OP_WRITE_CMD, 0x52) | | ''AttRecvNotification(fd: int64, handleOut: int64, dataBuf: int64, bufLen: int64): int64'' | Empfängt ATT_OP_HANDLE_VALUE_NTF | ==== ATT-Konstanten (Auswahl) ==== ^ Konstante ^ Wert ^ Beschreibung ^ | ''ATT_DEFAULT_MTU'' | 23 | Standard BLE ATT MTU | | ''ATT_MAX_MTU'' | 517 | Maximal verhandelbare MTU | | ''ATT_OP_READ_REQ'' | 10 | Lese-Request | | ''ATT_OP_WRITE_REQ'' | 18 | Schreib-Request (mit ACK) | | ''ATT_OP_WRITE_CMD'' | 82 | Schreib-Command (ohne ACK) | | ''ATT_OP_HANDLE_VALUE_NTF'' | 27 | Notification (kein ACK) | | ''ATT_OP_HANDLE_VALUE_IND'' | 29 | Indication (ACK erforderlich) | ---- ===== std.hardware.bluetooth_gattc ===== GATT-Client baut auf einem L2CAP/ATT-fd auf. Der fd wird vorher via ''L2CapConnect'' erzeugt. Servicelisten und Characteristic-Listen werden in heap-allokierten Puffern gehalten; Accessor-Funktionen lesen einzelne Felder heraus. ==== Service-Konstanten ==== ^ Konstante ^ UUID ^ Beschreibung ^ | ''GATT_SVC_GENERIC_ACCESS'' | 0x1800 | Generic Access Service | | ''GATT_SVC_GENERIC_ATTRIBUTE'' | 0x1801 | Generic Attribute Service | | ''GATT_SVC_HEART_RATE'' | 0x180D | Heart Rate Service | | ''GATT_SVC_BATTERY'' | 0x180F | Battery Service | | ''GATT_SVC_DEVICE_INFO'' | 0x180A | Device Information Service | | ''GATT_SVC_CURRENT_TIME'' | 0x1805 | Current Time Service | ==== Characteristic-UUID-Konstanten ==== ^ Konstante ^ UUID ^ Beschreibung ^ | ''GATT_UUID_DEVICE_NAME'' | 0x2A00 | Gerätename | | ''GATT_UUID_HR_MEASUREMENT'' | 0x2A37 | Heart Rate Measurement | | ''GATT_UUID_HR_BODY_LOCATION'' | 0x2A38 | Body Sensor Location | | ''GATT_UUID_BATTERY_LEVEL'' | 0x2A19 | Akkustand (0–100 %) | | ''GATT_UUID_FIRMWARE_REV'' | 0x2A26 | Firmware-Revision | | ''GATT_UUID_MODEL_NUMBER'' | 0x2A24 | Modellnummer | | ''GATT_UUID_CCCD'' | 0x2902 | Client Characteristic Configuration (Notification-Enable) | ==== Properties-Bits ==== ^ Konstante ^ Beschreibung ^ | ''GATT_PROP_READ'' | Characteristic ist lesbar | | ''GATT_PROP_WRITE_NO_RSP'' | Schreiben ohne Antwort (Write Command) | | ''GATT_PROP_WRITE'' | Schreiben mit Antwort (Write Request) | | ''GATT_PROP_NOTIFY'' | Server kann Notifications senden | | ''GATT_PROP_INDICATE'' | Server kann Indications senden (mit ACK) | ==== Discovery-Funktionen ==== ^ Signatur ^ Beschreibung ^ | ''GattDiscoverServices(fd: int64, outBuf: int64, maxServices: int64): int64'' | Entdeckt alle Primary Services; gibt Anzahl zurück | | ''GattDiscoverChars(fd: int64, startHandle: int64, endHandle: int64, outBuf: int64, maxChars: int64): int64'' | Entdeckt Characteristics in einem Service-Handle-Bereich | | ''GattFindServiceByUUID(svcBuf: int64, svcCount: int64, uuid: int64): int64'' | Sucht Service-Index nach UUID; −1 wenn nicht gefunden | | ''GattFindCharByUUID(charBuf: int64, charCount: int64, uuid: int64): int64'' | Sucht Characteristic-Index nach UUID; −1 wenn nicht gefunden | ==== Puffer-Accessoren ==== Direktzugriff auf den internen Puffer: ^ Signatur ^ Beschreibung ^ | ''GattSvcStart(buf: int64, idx: int64): int64'' | Start-Handle des Services | | ''GattSvcEnd(buf: int64, idx: int64): int64'' | End-Handle des Services | | ''GattSvcUUID(buf: int64, idx: int64): int64'' | UUID des Services (16-Bit) | | ''GattCharDecl(buf: int64, idx: int64): int64'' | Declaration-Handle der Characteristic | | ''GattCharValue(buf: int64, idx: int64): int64'' | Value-Handle der Characteristic | | ''GattCharUUID(buf: int64, idx: int64): int64'' | UUID der Characteristic (16-Bit) | | ''GattCharProps(buf: int64, idx: int64): int64'' | Properties-Bitmask der Characteristic | ==== Read/Write/Notify ==== ^ Signatur ^ Beschreibung ^ | ''GattReadChar(fd: int64, valueHandle: int64, dataBuf: int64, bufLen: int64): int64'' | Liest Characteristic-Wert | | ''GattWriteChar(fd: int64, valueHandle: int64, data: int64, dataLen: int64): int64'' | Schreibt Wert mit Antwort | | ''GattWriteCmd(fd: int64, valueHandle: int64, data: int64, dataLen: int64): int64'' | Schreibt ohne Antwort | | ''GattEnableNotification(fd: int64, cccdHandle: int64): int64'' | Aktiviert Notifications (schreibt 0x0001 in CCCD) | | ''GattDisableNotification(fd: int64, cccdHandle: int64): int64'' | Deaktiviert Notifications | | ''GattEnableIndication(fd: int64, cccdHandle: int64): int64'' | Aktiviert Indications (schreibt 0x0002 in CCCD) | | ''GattRecvNotification(fd: int64, handleOut: int64, dataBuf: int64, bufLen: int64): int64'' | Empfängt nächste Notification; schreibt Handle nach handleOut | | ''GattPoll(fd: int64, timeoutMs: int64): int64'' | Wartet auf Notification/Indication | | ''ReadHeartRate(fd: int64, hrHandle: int64, ...): int64'' | High-Level-Helfer: liest Herzrate als BPM | | ''ReadBatteryLevel(fd: int64, battHandle: int64): int64'' | High-Level-Helfer: liest Akkustand (0–100) | import std.hardware.bluetooth_l2cap; import std.hardware.bluetooth_gattc; import std.hardware.bluetooth_types; import std.alloc; import std.io; fn ReadBattery(addrStr: pchar): int64 { var addr := BTStrToAddr(addrStr); var fd := L2CapConnect(addr, BT_PSM_ATT, BDADDR_LE_PUBLIC); AttExchangeMtu(fd, 512); var svcBuf: int64 := alloc(GATT_SVC_RECORD_SIZE * 16); var svcCount := GattDiscoverServices(fd, svcBuf, 16); var idx := GattFindServiceByUUID(svcBuf, svcCount, GATT_SVC_BATTERY); var charBuf: int64 := alloc(GATT_CHAR_RECORD_SIZE * 8); GattDiscoverChars(fd, GattSvcStart(svcBuf, idx), GattSvcEnd(svcBuf, idx), charBuf, 8); var cidx := GattFindCharByUUID(charBuf, 8, GATT_UUID_BATTERY_LEVEL); var valBuf: int64 := alloc(4); GattReadChar(fd, GattCharValue(charBuf, cidx), valBuf, 4); var level: int64 := peek8(valBuf); L2CapClose(fd); free(svcBuf, GATT_SVC_RECORD_SIZE * 16); free(charBuf, GATT_CHAR_RECORD_SIZE * 8); free(valBuf, 4); return level; } fn MonitorHeartRate(addrStr: pchar): void { var addr := BTStrToAddr(addrStr); var fd := L2CapConnect(addr, BT_PSM_ATT, BDADDR_LE_PUBLIC); AttExchangeMtu(fd, 512); var svcBuf: int64 := alloc(GATT_SVC_RECORD_SIZE * 16); var svcCount := GattDiscoverServices(fd, svcBuf, 16); var idx := GattFindServiceByUUID(svcBuf, svcCount, GATT_SVC_HEART_RATE); var charBuf: int64 := alloc(GATT_CHAR_RECORD_SIZE * 8); GattDiscoverChars(fd, GattSvcStart(svcBuf, idx), GattSvcEnd(svcBuf, idx), charBuf, 8); var cidx := GattFindCharByUUID(charBuf, 8, GATT_UUID_HR_MEASUREMENT); GattEnableNotification(fd, GattCharValue(charBuf, cidx) + 1); // CCCD handle var ntfBuf: int64 := alloc(32); var handleOut: int64 := alloc(8); var i: int64 := 0; while (i < 10) { GattPoll(fd, 5000); GattRecvNotification(fd, handleOut, ntfBuf, 32); Print("BPM: "); PrintLn(IntToStr(peek8(ntfBuf + 1))); // Byte 0 = Flags, Byte 1 = BPM i := i + 1; } L2CapClose(fd); } ---- ===== std.hardware.bluetooth_gatts ===== GATT-Server registriert Services über D-Bus und macht das Gerät zum BLE-Peripheral. Erfordert eine aktive ''BlueZOpenConnection''. ==== Puffer-Accessoren ==== Direktzugriff auf den internen Puffer: ^ Signatur ^ Beschreibung ^ | ''GattsCharDefUUID(buf: int64, idx: int64): int64'' | UUID der Characteristic-Definition | | ''GattsCharDefProps(buf: int64, idx: int64): int64'' | Properties-Bits | | ''GattsCharDefValuePtr(buf: int64, idx: int64): int64'' | Zeiger auf aktuellen Wert | | ''GattsCharDefValueLen(buf: int64, idx: int64): int64'' | Länge des aktuellen Werts | | ''GattsCharDefSetValue(buf: int64, idx: int64, ptr: int64, len: int64)'' | Setzt neuen Wert | ==== Server-Funktionen ==== ^ Signatur ^ Beschreibung ^ | ''GattServerRegister(dbusFd: int64, ...): int64'' | Registriert Service-Struktur via D-Bus bei BlueZ | | ''GattServerHandleNext(fd: int64, svcUUID: int64, ...): int64'' | Verarbeitet nächste eingehende Read/Write-Anfrage | | ''GattServerSendNotification(fd: int64, ...): int64'' | Sendet Notification an verbundene Centrals | ---- ===== std.hardware.bluetooth_ext ===== Ergänzungen für aktives BLE-Scanning, Advertising-Pakete und Bluetooth-Mesh. ==== Scan-Puffer-Konstanten ==== ^ Konstante ^ Wert ^ Beschreibung ^ | ''BLE_SCAN_RESULT_SIZE'' | 128 | Größe eines einzelnen Scan-Ergebnis-Eintrags | ==== Scan-Ergebnis-Accessoren ==== ^ Signatur ^ Beschreibung ^ | ''BleScanResultAddr(buf: int64, idx: int64): int64'' | Zeiger auf Geräteadresse (6 Bytes) | | ''BleScanResultRSSI(buf: int64, idx: int64): int64'' | Signalstärke in dBm | | ''BleScanResultIsConnectable(buf: int64, idx: int64): int64'' | 1 wenn Gerät verbindbar | | ''BleScanResultNameLen(buf: int64, idx: int64): int64'' | Länge des Gerätenamens | | ''BleScanResultName(buf: int64, idx: int64): int64'' | Zeiger auf Gerätenamen | | ''BleScanResultAdvLen(buf: int64, idx: int64): int64'' | Länge der Advertising-Daten | | ''BleScanResultAdvData(buf: int64, idx: int64): int64'' | Zeiger auf rohe Advertising-Daten | ==== Scanner-Funktionen ==== ^ Signatur ^ Beschreibung ^ | ''BleScannerStart(fd: int64, adapterPath: int64, pathLen: int64): int64'' | Startet BLE-Scan via BlueZ | | ''BleScannerStop(fd: int64, adapterPath: int64, pathLen: int64): int64'' | Stoppt Scan | | ''BleScannerReadNext(fd: int64, result: int64): int64'' | Liest nächstes Scan-Ergebnis in result-Puffer | | ''BleScan(fd: int64, adapterPath: int64, pathLen: int64, ...): int64'' | Kombiniert Start, Collect und Stop | ==== Advertising-Konstanten ==== ^ Konstante ^ Beschreibung ^ | ''BLE_ADV_TYPE_PERIPHERAL'' | Verbindbares Advertising (Peripheral-Rolle) | | ''BLE_ADV_TYPE_BROADCAST'' | Nicht-verbindbares Advertising (Beacon) | | ''BLE_ADV_CONFIG_SIZE'' | Größe des Advertising-Konfigurations-Puffers | ==== Advertising-Funktionen ==== ^ Signatur ^ Beschreibung ^ | ''BleAdvertisementRegister(fd: int64, advConfig: int64, serial: int64): int64'' | Registriert Advertising-Konfiguration bei BlueZ | | ''BleAdvertisementHandleGetAll(fd: int64, advConfig: int64, serial: int64): int64'' | Verarbeitet eingehende D-Bus-Nachrichten für Advertising | | ''BleAdvertisementUnregister(fd: int64, ...): int64'' | Stoppt Advertising | ==== Mesh-Funktionen ==== ^ Signatur ^ Beschreibung ^ | ''MeshNetworkJoin(fd: int64, uuid: int64): int64'' | Tritt einem Bluetooth-Mesh-Netzwerk bei | | ''MeshSend(fd: int64, dst: int64, data: int64, dataLen: int64): int64'' | Sendet Mesh-Nachricht an Adresse | | ''MeshRecv(fd: int64, srcOut: int64, dataBuf: int64, bufLen: int64): int64'' | Empfängt Mesh-Nachricht; schreibt Quelladresse nach srcOut | import std.hardware.bluetooth_ext; import std.hardware.bluetooth_dbus; import std.hardware.bluetooth_types; import std.alloc; import std.io; fn ScanAndPrint(): void { var fd := BlueZOpenConnection(); var path: pchar := "/org/bluez/hci0"; var resultBuf: int64 := alloc(BLE_SCAN_RESULT_SIZE * 32); var count := BleScan(fd, path, 16, resultBuf, 32); var i: int64 := 0; while (i < count) { if (BleScanResultIsConnectable(resultBuf, i) != 0) { var nameBuf: int64 := alloc(64); var nameLen := BleScanResultNameLen(resultBuf, i); // Name-Bytes kopieren … PrintLn("RSSI: " + IntToStr(BleScanResultRSSI(resultBuf, i)) + " dBm"); free(nameBuf, 64); } i := i + 1; } BlueZClose(fd); free(resultBuf, BLE_SCAN_RESULT_SIZE * 32); } ---- ===== std.hardware.bluetooth_ai ===== KI-native Bluetooth-Profile: Definiert Standard-BLE-Profile als typsichere Compiler-Typen, sodass manuelle UUID-Verwaltung und Buffer-Arithmetik entfallen. Wrapper-Schicht über ''bluetooth_gattc''. import std.hardware.bluetooth_ai; import std.hardware.bluetooth_types; var addr := BTStrToAddr("AA:BB:CC:DD:EE:FF"); // Typsichere Profile — Compiler kennt die Semantik var sensor: BleSensor; sensor.Connect(addr); var bpm: HeartRateValue := sensor.Read(); PrintLn(IntToStr(bpm.value) + " bpm"); var batt: BleSensor; batt.Connect(addr); PrintLn(IntToStr(batt.Read().percent) + " %"); ==== Unterstützte Profile ==== ^ Profil-Typ ^ Service-UUID ^ Beschreibung ^ | ''BleSensor'' | 0x180D | Herzrate und Körperkontakt-Erkennung | | ''BleSensor'' | 0x180F | Akkustand (0–100 %) | | ''BleSensor'' | 0x1809 | Körper- oder Umgebungstemperatur | | ''BleSensor'' | 0x1808 | Blutzuckermessung | | ''BleSensor'' | 0x1810 | Blutdruck (systolisch/diastolisch) | | ''BleSensor'' | 0x1814 | Schrittanzahl und Distanz | | ''BleActuator'' | benutzerdefiniert | Generischer LED-Aktor | | ''BleActuator'' | benutzerdefiniert | Generischer Relais-Aktor | ---- ===== Verwandte Units ===== * ''[[lyx_-_programmiersprache:units:thread|std.thread]]'' — Threads für parallele Sensor-Verbindungen * ''[[lyx_-_programmiersprache:units:signals|std.signals]]'' — Signalbehandlung für sauberes Herunterfahren * ''[[lyx_-_programmiersprache:units:net:socket|std.net.socket]]'' — TCP/UDP-Netzwerkkommunikation * ''[[lyx_-_programmiersprache:units:android:ioctl|std.android.ioctl]]'' — ioctl-Nummern für Android-Bluetooth-Treiber Letzte Aktualisierung: 2026-06-05