Sensoren Aktoren Programmieren in C C Bluetooth Smart
Sensoren & Aktoren Programmieren in C / C++ Bluetooth Smart aka Bluetooth Low Energy Hochschule Fulda – FB AI Sommersemester 2021 http: //c. rz. hs-fulda. de Peter Klingebiel, HS Fulda, FB AI
Bluetooth 1 • Bluetooth Industriestandard für Datenübertragung zwischen Geräten per Funk über kurze Distanzen • BT nutzt das 2. 4 GHz-Band (wie Wi. Fi) • gemäß IEEE 802. 15. 1 durch die Bluetooth Special Interest Group (Bluetooth SIG) standardisiert • enstanden in den 1990 er Jahren Ersatz von kabelbasierten durch kabellose Verbindungen – 1999 Bluetooth 1. 0 – erste standardisierte Version Empfang bis 706. 25 k. Bit/s, Senden bis 57. 6 k. Bit/s – 2004 Bluetooth 2. 0 – bis zu 2. 1 Mbit/s – ab 2009 Bluetooth 4. 0 – BLE (Low Energy) – ab 2014 Bluetooth 4. 2 (Sicherheit , Bandbreite ) – ab 2016: Bluetooth 5. 0 (Reichweite , Bandbreite ) 2
Bluetooth 2 • 48 Bit MAC-Adresse, Form: xx. xx: xx: xx • Reichweiten und Leistungen • BT Classic Master-Slave Konzept – Master: inquiry message, danach page message – Slave: sendet Adresse und Namen, dann pairing – BT Classic erlaubt bis zu 7 Verbindungen gleichzeitig • BLE Konzept sehr viel komplexer • BLE erlaubt auch verbindungslosen Betrieb 3
Bluetooth 3 4
Bluetooth. Serial 1 • ESP 32: relativ einfache Programmierung mittels der speziellen Klasse Bluetooth. Serial #include <Bluetooth. Serial. h> // Objekt bt. Serial instantiieren Bluetooth. Serial bt. Serial; void setup() { Serial. begin(115200); // BT-Namen einstellen bt. Serial. begin("ESP-BT"); } void loop() { if(Serial. available() > 0) bt. Serial. write(Serial. read()); if(bt. Serial. available() > 0) Serial. write(bt. Serial. read()); } 5
Bluetooth Verbindung 1 • 1. Schritt: BT-Geräte koppeln (z. B. Windows 10) – – – Bluetooth muss aktiviert sein Bluetooth-Geräte Bluetooth-Gerät hinzufügen BT-Gerät (z. B. ESP 32 -BT) koppeln (pairing) ggfs. Kopplungskode angeben BT-Gerät ist nach Koppeln noch nicht verbunden! • 2. Schritt: mit BT-Gerät verbinden – COM-Port des BT-Geräts ermitteln (mit Geräte-Manager, BT -Eigenschaften, Arduino Serial Monitor o. ä. oder ausprobieren) – serielle Verbindung zum BT-Gerät aufbauen – z. B. mit putty: Serial auswählen, Serial Line auf COM-Port und Speed (Baudrate) z. B. auf 9600 einstellen und verbinden … 6
Bluetooth Verbindung 2 • Kommunikation mit Android Apps • Apple i. OS unterstützt nur BLE, kein Classic! • 1. Schritt: BT-Gerät koppeln – – Bluetooth muss aktiviert sein Einstellungen Bluetooth verfügbare Geräte BT-Gerät (z. B. ESP 32 -BT) koppeln (pairing) BT-Gerät ist nach Koppeln noch nicht verbunden! • 2. Schritt: Smartphone mit BT-Gerät verbinden – spezielle App starten, z. B. Serial Bluetooth Terminal – Devices (Bluetooth Classic) BT-Gerät auswählen – und kommunizieren … 7
Bluetooth Serial Programmierung 1 • weiteres einfaches Beispiel: Schalten einer LED • ESP 32 -Sketch const int pin = 19; // LED an Pin 19 int led = LOW; // Zustand der LED #include <Bluetooth. Serial. h> Bluetooth. Serial bt. Serial; // BT-Objekt void setup() { bt. Serial. begin("ESP-LED"); // BT-Name pin. Mode(pin, OUTPUT); } void loop() { if(bt. Serial. available() > 0) { char c = bt. Serial. read(); if(c == ’#’) digital. Write(pin, led = !led); } } 8
Bluetooth Low Energy 1 • Bluetooth: bewährtes und stabiles Verfahren für sehr viele Anwendungen in vielen Bereichen • Viele Anwendungsprofile wie RFCOMM, A 2 DP, . . . • Bluetooth 4. 0 führt Low-Energy-Funktionalität ein • Ziele von BLE – – – geringer Stromverbrauch (z. B. für Sensoren, Aktoren …) kostengünstig stabiles, robustes und sicheres Kommunikationsverfahren einfach zu implementieren vordefinierte Profile für verschiedene Einsatzbereiche hohe Verfügbarkeit (viele Plattformen) • BT-Geräte arbeiten im Single-Mode (BT Classic oder BLE) oder im Dual-Mode mit beiden BT-Verfahren 9
BLE Architektur 1 Application GATT GAP SM ATT L 2 CAP HCI Link Layer RF and PHY 10
BLE Architektur 2 • GATT: Generic Attribute Protocol Gruppierung von Attributen zu Services (z. B. Heart Rate) • GAP: Generic Access Protocol Advertising, Verbindungskontrolle, Broadcasting • SM: Security Manager Sicherheit, Verschlüsselung, Privacy • ATT: Attribute Protocol Management des Datentransfers zwischen BLE-Geräten • L 2 CAP Logical Link Control and Adaption Protocol • HCI: Host Controller Interface Standardisierte Kommunikation Controller - Host • Link + Physical Layer oft in Controller zusammengefasst • Link Layer: Pakete, Funksteuerung, Verschlüsselung • Physical Layer: Funkübertragung 11
Advertisement 1 • Advertisement - fundamentale Operation in BLE für ein Gerät, um eigene Dienste per Broadcast anzubieten und eine Verbindung aufzubauen Scanner Advertisement Device found Advertisement 12
Passives Scanning 1 • Scanning - fundamentale Operation in BLE für ein Gerät, um Dienste nachzufragen und eine Verbindung aufzubauen. Variante 1: Passives Scanning Scanner Advertisement Device found Advertisement 13
Aktives Scanning 1 • Scanner hört auf eingehende Advertisements, sendet dann einen Scan Request und wartet auf einen Scan Response (Namen, Dienste usw. ) Scanner Advertisement Scan Request Scan Response Device found (Name, Services) 14
Connections 1 • Während der Verbindung werden Daten robust und sicher vom Advertiser/Slave zum Initiator/Master übertragen. Aufbau und Abbau der Verbindung und Datentransfer: Initiator Advertisement Advertising Channels Connect Request Master „poll“ Data Channels Slave Total time < 3 ms ack LL terminate ack 15
Netzwerktopologien 1 • Geräte können bei BLE mehrere Rollen einnehmen • Advertiser Gerät sendet per Broadcasts Advertisement-Pakete, kann aber selber keine solchen annehmen • Scanner Gerät hört auf Advertisements und baut Verbindung auf • Slave Gerät ist zu einem (BT 4. 0) oder mehreren (BT >4. 1) Mastern verbunden und kann Daten senden und empfangen • Master Gerät ist zu einem oder mehreren Slaves verbunden, mit denen Daten ausgetauscht werden. Theoretisch sind beliebig viele Slave. Verbindungen zulässig, praktisch eher 4 bis 20 Slaves gleichzeitig • Hybrid Gerät kann Advertiser und Scanner, Slave und Master sein 16
Netzwerktopologien 2 • Broadcast-Topologie, BLE Peripheral (z. B. Sensor) sendet Advertisements an Central Devices (z. B. Smartphone) Central Device Peripheral Device (Sensor) Central Device 17
Netzwerktopologien 3 • Connected-Topologie, BLE Peripheral Slave und ist mit Central Device Master zum Datentransfer verbunden Peripheral Device Central Device (Phone, Tablet, Computer) Peripheral Device 18
Services und Characteristics 1 • BLE-Datentransfer erfolgt über GATT-Transaktionen • diese basieren auf abstrakten, verschachelten Objekten namens Profiles, Services und Characteristics • Profile – vordefinierte Sammlung von Services, normiert von der Bluetooth SIG oder festgelegt vom Designer des Peripheral Device, z. B. Heart Rate Profile • Services – fassen logische Daten (Characteristics) zusammen und werden über eine Service-UUID charakterisiert, z. B. Heart Rate Measurement (HRM) • Characteristics – Container, die eigentlichen Daten enthalten, werden über Characteristic-UUID adressiert. • UUID – 16 Bit für genormte Dienste (von der BT SIG festgelegt) und Daten und 128 Bit für nutzerspezifische Dienste und Daten • mehr auf der Seite der BT SIG → https: //www. bluetooth. com 19
Services und Characteristics 2 • GATT Protokoll mit Profile, Services und Characteristics Profile Service Characteristic Service Characteristic 20
Services und Characteristics 3 21
BLE-Rollen 1 • BLE-Geräte übernehmen verschiedene Rollen • Peripheral Device, z. B. Sensor, stellt einen oder mehrere Dienste zur Verfügung, die von Central Device nachgefragt werden können • Serviceanbieter • Advertiser Bekanntmachen der Dienste (Broadcast) • Slave Verbindungsaufbau (GAP-Rolle) • Server Liefern von Daten (GATT-Rolle) • Central Device, z. B. Smartphone oder Computer, fragt Dienste und Daten nach und verarbeitet diese weiter • Servicenachfrager • Initiator Suche nach Advertisern und Verbindungsaufbau • Master Verbindungsaufbau (GAP-Rolle) • Client Empfangen von Daten (GATT-Rolle) 22
Programmierung ESP 32 1 • ESP 32 unterstützt neben Bluetooth Classic (mit der Klasse Bluetooth. Serial) auch Bluetooth 4. 2 BLE • die Programmierung auf dem „low-level“ z. B. mit der ESP-IDF und den Bibliotheken von Espressif gestaltet sich ziemlich mühsam, fehleranfällig und frickelig • der amerikanische Informatiker Neil • • Kolban beschäftigt sich schon lange mit den CPUs von Espressif und hat zum ESP 8266 und zum ESP 32 sehr gute Bücher veröffentlicht von ihm stammt auch die BLE-Library zum ESP 32 in der Arduino IDE damit ist die BLE-Programmierung deutlich einfacher und komfortabler → https: //leanpub. com/kolban-ESP 32 → https: //github. com/nkolban 23
Programmierung ESP 32 2 • Kolban führt für die BLE-Programmierung des ESP 32 anstelle der low-level C-Funktionen hochwertige C++-Klassen ein, in denen die verschiedenen Konzepte und Rollen von BLE implementiert sind und die Details weitgehend verbergen • die BLE-Klassen sind in der Arduino BLE-Library enthalten • damit ist die objektorientierte Modellierung und Implementierung von BLE-Programmen oder -Sketches verhältnismäßig komfortabel möglich • wesentliche Konzepte der Klassen sind • BLE Server (= BLE Peripheral = Slave) mit Services, Characteristics und Descriptors sowie mit Advertisements • BLE Client (= BLE Central Device = Master) mit Scanning, Verbindungsaufbau und Kommunikation mit Peripherals / Servern 24
BLE Server 1 • BLEDevice modelliert die BLE-Komponenten des ESP 32 • BLEServer bildet einen BLE-Server ab • BLEService modelliert einen Service und gehört zu einen Server • BLECharacteristic modelliert eine Characteristic, also die eigentlichen Daten und gehört zu einem Service • BLEDescriptor bildet einen Descriptor ab und gehört zu einer Characteristic • BLEAdvertising modelliert das Advertising und gehört zu einem Server, um anderen (Central Device = Master = Client) die eigenen Dienste, also Services und Characteristics anzubieten 25
BLE Server 2 • damit lässt sich ein BLE-Server auf relativ hohem und abstraktem Niveau programmieren // BLE-Umgebung initialisieren BLEDevice: : init("Server. Name"); // BLE-Server erzeugen BLEServer *p. Server = BLEDevice: : create. Server(); // BLE-Service erzeugen BLEService *p. Service = p. Server->create. Service(SUUID); // BLE-Characteristic erzeugen BLECharacteristic *p. Characteristic = p. Service->create. Characteristic(CUUID, props); // Characteristicdaten setzen p. Characteristic->set. Value("Hi, hier ist der Sensor"); // Service starten p. Service->start(); 26
BLE Server 3 • das Advertising gestaltet sich dann folgendermaßen // BLE-Advertising erzeugen BLEAdvertising *p. Advertising = p. Server->get. Advertising(); // Advertising-Daten erzeugen BLEAdvertisement. Data advertisement. Data; // Eigenschaften der Advertisement-Daten setzen p. Advertising->set. Advertisement. Data(advertisement. Data); // Advertising starten p. Advertising->start(); 27
BLE Server 4 • ein Kernkonzept von BLE ist das Konzept der Characteristic, der Container, in denen die Daten gehalten und transferiert werden • Umsetzung mit der Klasse BLECharacteristic. Callbacks mit den beiden Methoden on. Read() und on. Write() // Callbacks erzeugen class My. Callbacks: public BLECharacteristic. Callbacks { // aufgerufen bei einem Read-Request void on. Read(BLECharacteristic *p. Characteristic) { // Daten data ermitteln und senden p. Characteristic->set. Value(data); } // aufgerufen bei einem Write-Request void on. Write(BLECharacteristic *p. Characteristic) { // Daten data lesen und verarbeiten data = p. Characteristic->get. Value(); } } // Callbackhandler einhaengen p. Characteristic->set. Callbacks(new My. Callbacks()); 28
BLE Server 5 • um auf Aufbau und Abbau einer Verbindung zu Clients reagieren zu können, dient die Servercallbacks-Klasse BLEServer. Callbacks mit den beiden Methoden on. Connect() und on. Disconnect() // Servercallbacks erzeugen class My. Server. Callbacks: public BLEServer. Callbacks { // aufgerufen beim Aufbau der Verbindung void on. Connect(BLEServer *p. Server) { // z. B. Flag setzen connected = true } // aufgerufen beim Abbau der Verbindung void on. Disconnect(BLEServer *p. Server) { // z. B. Flag ruecksetzen connected = false; } } // Callbackhandler einhaengen p. Server->set. Callbacks(new My. Server. Callbacks()); 29
BLE Server 6 • Server liefern i. a. Daten, z. B. Sensorwerte • daher ist es sinnvoll, neue Daten zu pushen, wenn diese anliegen, und so das unnötige und zeitaufwendige Pollen von Clients zu verhindern • dazu kennt BLE die Konzepte des notify und des indicate • indicate erwartet eine Bestätigung seitens des Clients über das Lesen der Daten • notify liefert die Daten ohne Bestätigung • dazu dienen die beiden Methoden der Characteristic-Klasse notify() und indicate() // gerade gelesenen Wert data setzen p. Characteristic->set. Value(data); // und pushen, d. h. notify ausloesen p. Characteristic->notify(); 30
BLE Client 1 • Clients lesen i. a. Daten von Servern, z. B. Sensorwerte • der Verbindungsaufbau über die Serveradresse ist i. a. eher ungünstig, da die Adresse dann im Programm fest kodiert ist • sinnvoller ist ein BLE-Scan mit dem Objekt BLEScan und der Methode get. Scan() des BLEDevice sowie den Methoden der Klasse BLEAdvertised. Device. Callbacks class My. Callbacks: public BLEAdvertised. Device. Callbacks { void on. Result(BLEAdvertised. Device advertised. Device) { // Aktion, wenn Device gefunden wurde } }; // BLE (ohne Namen) initialisieren BLEDevice. init(""); // Scan initialisieren und Callbacks einhaengen BLEScan *p. My. Scan = BLEDevice: : get. Scan(); p. My. Scan->set. Advertised. Device. Callbacks(new My. Callbacks()); // Scan fuer 10 Sekunden starten p. My. Scan. start(10); 31
BLE Client 2 • die Instanz von BLEAdvertised. Device liefert eine Fülle von Eigenschaften und Daten des Servers, darunter den Namen, die Adresse, RSSI, primäre Service UUID u. v. a. mehr • so kann im Callback z. B. die Service UUID geprüft werden if(advertised. Device. has. Service. UUID()) { BLEUUID service = advertised. Device. get. Service. UUID(); if(service. equals(BLEUUID(wanted_uuid)) { // Device / Server mit Service gefunden. . . } } • wurde der Server gefunden, kann der Scan gestoppt werden advertised. Device. get. Scan()->stop(); • dann kann die Verbindung zum Server aufgebaut werden // Client Objekt erzeugen BLEClient *p. My. Client = BLEDevice: : create. Client(); // dann mit Server verbinden p. My. Client->connect(advertised. Device. get. Address()); 32
BLE Client 3 • nach Verbindungsaufbau zum Server kann der gewünschte Service und die gewünschte Characteristic ausgelesen werden // Service ermitteln und erzeugen BLERemote. Service *p. My. Remote. Service = p. Client->get. Service(service. UUID); // Characteristic ermitteln und erzeugen BLERemote. Characteristic *p. My. Remote. Characteristic = p. My. Remote. Service->get. Characteristic(char. UUID); // dann sind die Daten lesbar. . . my. Value = p. My. Remote. Characteristic->read. Value(); //. . . oder schreibbar p. My. Remote. Characteristic->write. Value(value); • mit der Methode register. For. Notify() wird ein Handler notify. Callback() für Notify-Events installiert void notify. Callback(BLERemote. Characteristic *p. Char, uint 8_t *data, size_t length, bool is. Notify) { // Daten auslesen } p. My. Remote. Characteristic->register. For. Notify(notify. Callback); 33
- Slides: 33