Bluetooth ist einer der effizientesten drahtlosen Funkstandards mit kurzer Reichweite für den Datenaustausch über Ultrahochfrequenz-Funkwellen (typischerweise 2,4 GHz) und den Aufbau von Personal Area Networks (PAN). Grundsätzlich wurde die Bluetooth-Technologie als Kabelersatzsystem entwickelt, sodass ihre Verwendung in eingebetteten Systemen unvermeidlich ist. Die meisten bekannten Mikrocontroller wie ESP32, Raspberry Pi, Arduino Mega haben eingebaute Bluetooth-Module, andere Mikrocontroller können mit Modulen wie HC 05 oder JDY-30 angepasst werden, um sie Bluetooth-kompatibel zu machen. Dieser Artikel wird dir helfen, das grundlegende Wissen über die Funktionsweise von Bluetooth-Modulen zwischen zwei ESP32’s zu bekommen und die Verbindung zwischen Raspberry Pi und ESP32 zu verstehen.
Benötigte Komponenten
Wir benötigen Folgendes:
- Raspberry Pi mit installierter PYQT-Bibliothek
- Arduino IDE
- Zwei ESP32-Entwicklungsplatinen
- NRF Application (App Store, Play Store)
- USB-Kabel für ESP32
Bluetooth Low Energy (BLE)
Die meisten Mikrocontroller, einschließlich Raspberry Pi und ESP32, verfügen über Bluetooth-Module, die auf der Bluetooth Low-Energy-Technologie basieren. BLE ist eine Low-Power-Variante von Bluetooth, die im Gegensatz zum klassischen Bluetooth auf eine sehr kurze Reichweite und eine geringe Bandbreite der zu übertragenden Daten auf kurzer Distanz ausgelegt ist. Da es sehr stromsparend ist, verbraucht es fast 100-mal weniger Energie als klassisches Bluetooth, mit einem sehr geringen Kompromiss bei der Leistung. BLE befindet sich im Schlafmodus, es sei denn, es wird eine Verbindung hergestellt oder die Übertragung von Daten ist erforderlich, im Gegensatz zum klassischen Bluetooth, das immer eingeschaltet ist.
Es arbeitet in vier Modi:
- Peripheriegerät – Das ist im Grunde ein Gerät, das die Daten anzeigt, aber es kann auch für die Verbindung mit anderen Geräten verwendet werden.
- Broadcaster – Ein Gerät, dessen einziger Zweck es ist, Daten zu verbreiten.
- Observer – Gerät, das nur nach den Daten sucht.
- Central – Dies ist ein Gerät mit doppeltem Verwendungszweck, das sowohl nach Daten suchen, als auch eine Verbindung zu ihnen herstellen kann.
Als BLE eingeführt wurde, wurden die ersten beiden Modi von Sensoren und anderen industriellen Geräten genutzt, die letzten beiden von Mobiltelefonen. Mit der Weiterentwicklung der Technologie bieten die meisten BLE-Systeme jedoch alle vier Übertragungsmodi. ESP32 und Raspberry Pi bieten ebenfalls diese vier Übertragungsmodi. In der folgenden Tabelle sehen wir den wesentlichen Unterschied zwischen der klassischen und der BLE-Übertragung.
Verbindung zwischen Zwei ESP32’s
Zwei ESP32 können auf eine sehr optimierte Weise mit BLE-Fähigkeit verbunden werden. Die Bluetooth-Verbindung zwischen zwei Boards wird so hergestellt, dass ein Board als Server und das andere als Client fungiert. Ein ESP32 wird als Server fungieren und die Daten bekannt geben und die Verbindung initiieren, der zweite ESP32 wird als Client fungieren und die Daten vom Server empfangen. Wir werden einige Strings von einem ESP32 zum anderen über eine BLE-Verbindung senden.
ESP32 als Server
Unser erster ESP32 wird als Bluetooth-Server fungieren. Er stellt die Verbindung und die Daten für den Client bereit. Sein Code lautet wie folgt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
#include <BLEDevice.h> #include <BLEUtils.h> #include <BLEServer.h> // See the following for generating UUIDs: // https://www.uuidgenerator.net/ #define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b" #define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8" void setup() { Serial.begin(115200); Serial.println("Starting BLE work!"); BLEDevice::init("ESP32 AS A BLE"); BLEServer *pServer = BLEDevice::createServer(); BLEService *pService = pServer->createService(SERVICE_UUID); BLECharacteristic *pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE ); pCharacteristic->setValue("Hi,other ESP32 here is your data"); pService->start(); // BLEAdvertising *pAdvertising = pServer->getAdvertising(); // this still is working for backward compatibility BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); pAdvertising->addServiceUUID(SERVICE_UUID); pAdvertising->setScanResponse(true); pAdvertising->setMinPreferred(0x06); pAdvertising->setMinPreferred(0x12); BLEDevice::startAdvertising(); Serial.println("Characteristic defined!"); } void loop() { // put your main code here, to run repeatedly: delay(2000); } |
Dieser Code verwendet die BLE-Klasse, um ihre Objekte wie Merkmale, BLE- und Werbeobjekte zu erstellen. Am Anfang stehen Merkmal und Service UUID. UUID, ein Akronym für Universally Unique ID, und entspricht einer eindeutigen Nummer, die zur Identifizierung von Diensten und Merkmalen verwendet wird, die ein Bluetooth-Gerät bereitstellen soll. In diesem Code haben wir zunächst drei Objekte der Klassen BLEserver, BLEcharacteristic und BLEService erstellt und mit den erforderlichen Werten initialisiert. Dann haben wir einfach die Funktion start advertising aus der BLE-Geräteklasse verwendet, um unseren Bluetooth-Server mit der bestimmten UUID, den Eigenschaften und den Diensten zu starten, die wir initialisiert haben. Wir können beliebige Daten wie z.B. Sensordaten oder andere benötigte Daten einstellen und mit der Werbung dafür beginnen. Sobald dieser Server gestartet ist, können wir mit nRF Connect in nur zwei Schritten von Ihrem Mobiltelefon aus darauf zugreifen:
Schritt 1: Öffne den Scanner und verbinde ihn mit deinem Bluetooth-Gerät.
Schritt 2: Nachdem du deinen ESP32 angeschlossen hast, kannst du die Charakteristik überprüfen, und es wird dein geschriebener Text angezeigt.
ESP32 as a Client
Wie der Name schon sagt, fungiert das zweite ESP32 als Client und greift auf die Daten des Servers zu. Er sollte lediglich die UUIDs der Merkmale und Dienste bereitstellen, um eine Verbindung zum Server herzustellen und auf die angegebenen Dienste des Servers zuzugreifen ESP32.
Der Code lautet wie folgt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
#include "BLEDevice.h" //#include "BLEScan.h" // The remote service we wish to connect to. static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b"); // The characteristic of the remote service we are interested in. static BLEUUID charUUID("beb5483e-36e1-4688-b7f5-ea07361b26a8"); static boolean doConnect = false; static boolean connected = false; static boolean doScan = false; static BLERemoteCharacteristic* pRemoteCharacteristic; static BLEAdvertisedDevice* myDevice; static void notifyCallback( BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) { Serial.print("Notify callback for characteristic "); Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str()); Serial.print(" of data length "); Serial.println(length); Serial.print("data: "); Serial.println((char*)pData); } class MyClientCallback : public BLEClientCallbacks { void onConnect(BLEClient* pclient) { } void onDisconnect(BLEClient* pclient) { connected = false; Serial.println("onDisconnect"); } }; bool connectToServer() { Serial.print("Forming a connection to "); Serial.println(myDevice->getAddress().toString().c_str()); BLEClient* pClient = BLEDevice::createClient(); Serial.println(" - Created client"); pClient->setClientCallbacks(new MyClientCallback()); // Connect to the remove BLE Server. pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private) Serial.println(" - Connected to server"); // Obtain a reference to the service we are after in the remote BLE server. BLERemoteService* pRemoteService = pClient->getService(serviceUUID); if (pRemoteService == nullptr) { Serial.print("Failed to find our service UUID: "); Serial.println(serviceUUID.toString().c_str()); pClient->disconnect(); return false; } Serial.println(" - Found our service"); // Obtain a reference to the characteristic in the service of the remote BLE server. pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID); if (pRemoteCharacteristic == nullptr) { Serial.print("Failed to find our characteristic UUID: "); Serial.println(charUUID.toString().c_str()); pClient->disconnect(); return false; } Serial.println(" - Found our characteristic"); // Read the value of the characteristic. if(pRemoteCharacteristic->canRead()) { std::string value = pRemoteCharacteristic->readValue(); Serial.print("The characteristic value was: "); Serial.println(value.c_str()); } if(pRemoteCharacteristic->canNotify()) pRemoteCharacteristic->registerForNotify(notifyCallback); connected = true; return true; } /** * Scan for BLE servers and find the first one that advertises the service we are looking for. */ class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { /** * Called for each advertising BLE server. */ void onResult(BLEAdvertisedDevice advertisedDevice) { Serial.print("BLE Advertised Device found: "); Serial.println(advertisedDevice.toString().c_str()); // We have found a device, let us now see if it contains the service we are looking for. if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) { BLEDevice::getScan()->stop(); myDevice = new BLEAdvertisedDevice(advertisedDevice); doConnect = true; doScan = true; } // Found our server } // onResult }; // MyAdvertisedDeviceCallbacks void setup() { Serial.begin(115200); Serial.println("Starting Arduino BLE Client application..."); BLEDevice::init(""); // Retrieve a Scanner and set the callback we want to use to be informed when we // have detected a new device. Specify that we want active scanning and start the // scan to run for 5 seconds. BLEScan* pBLEScan = BLEDevice::getScan(); pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); pBLEScan->setInterval(1349); pBLEScan->setWindow(449); pBLEScan->setActiveScan(true); pBLEScan->start(5, false); } // End of setup. // This is the Arduino main loop function. void loop() { // If the flag "doConnect" is true then we have scanned for and found the desired // BLE Server with which we wish to connect. Now we connect to it. Once we are // connected we set the connected flag to be true. if (doConnect == true) { if (connectToServer()) { Serial.println("We are now connected to the BLE Server."); } else { Serial.println("We have failed to connect to the server; there is nothin more we will do."); } doConnect = false; } // If we are connected to a peer BLE Server, update the characteristic each time we are reached // with the current time since boot. if (connected) { String newValue = "Time since boot: " + String(millis()/1000); Serial.println("Setting new characteristic value to \"" + newValue + "\""); // Set the characteristic's value to be the array of bytes that is actually a string. pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length()); }else if(doScan){ BLEDevice::getScan()->start(0); // this is just example to start scan after disconnect, most likely there is better way to do it in arduino } delay(1000); // Delay a second between loops. } // End of loop |
Dieser Code stützt sich auf einige benutzerdefinierte Funktionen. Wir haben das Merkmal und die UUID des Dienstes am Anfang des Codes definiert. Objekte der Klassen BLERemoteCharacteristic und BLEAdvertisedDevice werden zu Beginn erstellt und die Funktion connect to server () wird verwendet, um eine Verbindung zum Server (andere ESP32) herzustellen. Schließlich holt er alle vom Server bereitgestellten Daten mit Hilfe von Merkmals- und Dienstvariablen ab. Der serielle Monitor zeigt die folgenden Werte an:
Verbindung Zwischen ESP32 und Raspberry Pi
ESP32-Verbindung: Unser ESP32 wird eine UART-Verbindung über Bluetooth herstellen. So wird er in der Lage sein, auf zwei Arten mit dem Raspberry Pi zu kommunizieren.
Unser Code ist wie folgt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
#include <BLEDevice.h> #include <BLEServer.h> #include <BLEUtils.h> #include <BLE2902.h> BLEServer *pServer = NULL; BLECharacteristic * pTxCharacteristic; bool deviceConnected = false; bool oldDeviceConnected = false; uint8_t txValue = 0; // See the following for generating UUIDs: // https://www.uuidgenerator.net/ #define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID #define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" #define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" class MyServerCallbacks: public BLEServerCallbacks { void onConnect(BLEServer* pServer) { deviceConnected = true; }; void onDisconnect(BLEServer* pServer) { deviceConnected = false; } }; class MyCallbacks: public BLECharacteristicCallbacks { void onWrite(BLECharacteristic *pCharacteristic) { std::string rxValue = pCharacteristic->getValue(); if (rxValue.length() > 0) { Serial.println("*********"); Serial.print("Received Value: "); for (int i = 0; i < rxValue.length(); i++) Serial.print(rxValue[i]); Serial.println(); Serial.println("*********"); } } }; void setup() { Serial.begin(115200); // Create the BLE Device BLEDevice::init("UART Service For ESP32"); // Create the BLE Server pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks()); // Create the BLE Service BLEService *pService = pServer->createService(SERVICE_UUID); // Create a BLE Characteristic pTxCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY ); pTxCharacteristic->addDescriptor(new BLE2902()); BLECharacteristic * pRxCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE ); pRxCharacteristic->setCallbacks(new MyCallbacks()); // Start the service pService->start(); // Start advertising pServer->getAdvertising()->start(); Serial.println("Waiting a client connection to notify..."); } void loop() { if (deviceConnected) { pTxCharacteristic->setValue(&txValue, 1); pTxCharacteristic->notify(); txValue++; delay(10); // bluetooth stack will go into congestion, if too many packets are sent } // disconnecting if (!deviceConnected && oldDeviceConnected) { delay(500); // give the bluetooth stack the chance to get things ready pServer->startAdvertising(); // restart advertising Serial.println("start advertising"); oldDeviceConnected = deviceConnected; } // connecting if (deviceConnected && !oldDeviceConnected) { // do stuff here on connecting oldDeviceConnected = deviceConnected; } } |
Dieser Code besteht aus zwei Teilen, einer überträgt beliebige Daten in einer Schleife. Der andere empfängt Daten. Zu Beginn haben wir zwei Merkmale als RX und TX definiert, dann haben wir sie definiert und ihnen die richtigen Werte zugewiesen, je nach unserem Bedarf. Da wir UART verwenden, können wir gleichzeitig senden und empfangen, ohne dass es zu einer Behinderung kommt. Wir können eine Seite der Verbindung mit Hilfe der NRF-Anwendung testen (App store link: https://apps.apple.com/us/app/nrf-connect-for-mobile/id1054362403 Play store link: https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp). Lade den obigen Code hoch und öffne die Anwendung NRF Connector, verbinde dich mit dem UART-SERVICE als:
Gib nach dem Verbinden den Wert ein, den Du an den seriellen Monitor senden möchten. Ihr Wert wird an den seriellen Monitor gesendet.
Raspberry Pi Anschluss:
Auf dem Raspberry Pi läuft ein Python-Skript, das bluepy verwendet (eine spezielle Bibliothek des Raspberry Pi zur Verwendung des BLE-Modus). Im Grunde genommen entwickelt dieser Code eine einfache GUI, die dabei hilft, Daten vom ESP32 zu senden und zu empfangen. Du solltest PYQT und bluepy Bibliotheken installieren, bevor du fortfährst. Nachdem wir dies eingerichtet haben, führe einfach diesen Code aus und eine grafische Benutzeroberfläche wird auf dem Bildschirm angezeigt. Dann können wir die Daten eingeben, die über BLE an ESP32 gesendet werden sollen, oder es werden die vom ESP32 empfangenen Daten angezeigt. Dieser Anschluss ist ein UART (universally asynchronous receiver-transmitter). Das heißt, es kann gleichzeitig Daten senden und empfangen. Im ersten Textfeld werden die Daten von ESP32 empfangen und in das zweite Textfeld schreiben wir die Daten, die vom Raspberry Pi gesendet werden sollen.
Am ESP32 seriellen Kommunikationsmonitor haben wir:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
import sys import time import requests from PyQt5.QtCore import QObject, QRunnable, QThreadPool, QTimer, pyqtSignal, pyqtSlot from PyQt5.QtWidgets import ( QApplication, QLabel, QMainWindow, QPlainTextEdit, QPushButton, QVBoxLayout, QWidget, ) from bluepy import btle class WorkerSignals(QObject): signalMsg = pyqtSignal(str) signalRes = pyqtSignal(str) class MyDelegate(btle.DefaultDelegate): def __init__(self, sgn): btle.DefaultDelegate.__init__(self) self.sgn = sgn def handleNotification(self, cHandle, data): try: dataDecoded = data.decode() self.sgn.signalRes.emit(dataDecoded) except UnicodeError: print("UnicodeError: ", data) class WorkerBLE(QRunnable): def __init__(self): super().__init__() self.signals = WorkerSignals() self.rqsToSend = False @pyqtSlot() def run(self): self.signals.signalMsg.emit("WorkerBLE start") #--------------------------------------------- p = btle.Peripheral("3c:71:bf:0d:dd:6a") p.setDelegate( MyDelegate(self.signals) ) svc = p.getServiceByUUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E") self.ch_Tx = svc.getCharacteristics("6E400002-B5A3-F393-E0A9-E50E24DCCA9E")[0] ch_Rx = svc.getCharacteristics("6E400003-B5A3-F393-E0A9-E50E24DCCA9E")[0] setup_data = b"\x01\00" p.writeCharacteristic(ch_Rx.valHandle+1, setup_data) # BLE loop -------- while True: """ if p.waitForNotifications(1.0): # handleNotification() was called continue print("Waiting...") """ p.waitForNotifications(1.0) if self.rqsToSend: self.rqsToSend = False try: self.ch_Tx.write(self.bytestosend, True) except btle.BTLEException: print("btle.BTLEException"); #---------------------------------------------hellohello self.signals.signalMsg.emit("WorkerBLE end") def toSendBLE(self, tosend): self.bytestosend = bytes(tosend, 'utf-8') self.rqsToSend = True """ try: self.ch_Tx.write(bytestosend, True) except BTLEException: print("BTLEException"); """ class MainWindow(QMainWindow): def __init__(self): super().__init__() layout = QVBoxLayout() buttonStartBLE = QPushButton("Start BLE") buttonStartBLE.pressed.connect(self.startBLE) self.console = QPlainTextEdit() self.console.setReadOnly(True) self.outconsole = QPlainTextEdit() buttonSendBLE = QPushButton("Send message") buttonSendBLE.pressed.connect(self.sendBLE) layout.addWidget(buttonStartBLE) layout.addWidget(self.console) layout.addWidget(self.outconsole) layout.addWidget(buttonSendBLE) w = QWidget() w.setLayout(layout) self.setCentralWidget(w) self.show() self.threadpool = QThreadPool() print( "Multithreading with Maximum %d threads" % self.threadpool.maxThreadCount()) def startBLE(self): self.workerBLE = WorkerBLE() self.workerBLE.signals.signalMsg.connect(self.slotMsg) self.workerBLE.signals.signalRes.connect(self.slotRes) self.threadpool.start(self.workerBLE) def sendBLE(self): strToSend = self.outconsole.toPlainText() self.workerBLE.toSendBLE(strToSend) def slotMsg(self, msg): print(msg) def slotRes(self, res): self.console.appendPlainText(res) app = QApplication(sys.argv) window = MainWindow() app.exec() |
Praktische Anwendungen in der Industrie
BLE ist sehr vorteilhaft an Orten, an denen wir nicht genügend Strom zur Verfügung haben. Lass uns einige der praktischen Anwendungen besprechen:
Intelligentes landwirtschaftliches System: Ein Mikrocontroller wie ESP32 oder Raspberry Pi mit Ble-Fähigkeit kann wochenlang mit Batterien betrieben werden, um alle Sensordaten von einem ESP32 zu einem anderen ESP32 zu übertragen und so wichtige Maßnahmen für das richtige Wachstum der Pflanzen zu ergreifen (wie das Einschalten der Beleuchtung oder des Motors).
Sporttrainer: Ein Mikrocontroller kann verwendet werden, um Daten wie Herzschlag, Laufgeschwindigkeit oder andere von Sensoren gemessene Daten über Bluetooth an ein Mobiltelefon zu senden oder einfach auf einem Bildschirm wie dem max 7219 anzuzeigen. Wir können all diese Werte einfach und effizient ohne Verkabelung überwachen.
Systeme zur Gesundheitsüberwachung: Armbänder zur Messung verschiedener Daten wie Herzschlag, Blutdruck und anderer Dinge können über die BLE-Fähigkeit eines Mikrocontrollers direkt an einen Computer übertragen werden.
Hausautomatisierung: Die Hausautomatisierung ist eines der Geschenke, die kompakte Mikrocontroller möglich gemacht haben. BLE-Geräte können für sehr innovative Dinge verwendet werden, von der Steuerung von Lichtern bis hin zu Türen mit Fingerabdruckschlössern, alles ist möglich. Einige der interessanten Anwendungen sind:
- Erinnerungen für Geräte wie Herde, Wasserpumpen, Heizungen, Geysire, um sie zu einer bestimmten Zeit auszuschalten
- Mobil gesteuerte Sicherheitskameras
- Mobil gesteuerte automatische Garagentore (mit z. B. ESP32 oder Raspberry Pi)
- Erfassung verschiedener Sensordaten aus dem Haus (Feuer, Wasser, Bewegung, Licht)