commit 7fca9d7bdf9ecdf877414ac7fa604f5a1ba7ede1 Author: Thorsten Date: Sat Dec 21 20:13:08 2024 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..09224b6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch +settings-my-ignore.h \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..9a6e095 --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +# ESP8266 Ventilation Recomondation + +Ein Projekt zur Visualisierung von **Lüftungsempfelungen** mit einem **ESP8266**. +Das Script fragt periodisch eine Systemvariable von einer Homematic Zentrale ab. +Wenn die Variable wahr ist wird das mittels einer grünen LED angezeigt. + +Projektbild + + +## Funktionen +- **LED leuchtet grün** Lüften empfohlen +- **LED leuchtet rot** Lüften nicht empfohlen +- **LED blinkt cyan** WLAN wird verbunden + + +## Konfiguration + +Passe die `settings.h` auf deine Bedürfnisse an +```cpp +// ######################## WLAN-Daten ######################## + +const char* hostname = "ESP6288_Keller_Lueften"; + +const char* ssidList[] = { + "SSID_1", // Netzwerk 1 + "SSID_2", // Netzwerk 2 + "SSID_3" // Netzwerk 3 + // Weitere SSID hier hinzufügen +}; + +const char* passwordList[] = { + "Passwort_1", // Passwort für SSID 1 + "Passwort_2", // Passwort für SSID 2 + "Passwort_3" // Passwort für SSID 3 + // Weitere Passwörter hier hinzufügen +}; + +// ################# Homematic Systemvariable ################# + +const char* hm_sysvar_url = "http://192.168.178.50/addons/xmlapi/sysvar.cgi?sid=kYvzkyRPluLBsfLL&ise_id=20746"; + +// ############################################################ +``` + +## Verdrahtung + +| ESP8266 | LED | +|---------|-----| +| D1 | R | +| D2 | G | +| D3 | B | +| G | I | + + +Verdrahtung \ No newline at end of file diff --git a/images/image_1.jpg b/images/image_1.jpg new file mode 100644 index 0000000..6376190 Binary files /dev/null and b/images/image_1.jpg differ diff --git a/images/image_2.jpg b/images/image_2.jpg new file mode 100644 index 0000000..ec393b8 Binary files /dev/null and b/images/image_2.jpg differ diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..2593a33 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..58a91f8 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,18 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:nodemcuv2] +platform = espressif8266 +board = nodemcuv2 +framework = arduino +upload_speed = 115200 +monitor_speed = 115200 +;lib_deps = +; LiquidCrystal_I2C \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..16c2f74 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,178 @@ +#include +#include +#include +#include + + +int numNetworks = sizeof(ssidList) / sizeof(ssidList[0]); // Anzahl der Netzwerke +int current_ap = 0; // Start mit der ersten SSID +bool reconnecting = false; // Flag für den Reconnect-Status + +// Pin-Definitionen +int PinRED = 5; +int PinGREEN = 4; +int PinBLUE = 0; + +// Funktion, um die LED-Farbe zu setzen +void led_set_color(String color) { + if (color == "red") { + digitalWrite(PinRED, HIGH); + digitalWrite(PinGREEN, LOW); + digitalWrite(PinBLUE, LOW); + } else if (color == "green") { + digitalWrite(PinRED, LOW); + digitalWrite(PinGREEN, HIGH); + digitalWrite(PinBLUE, LOW); + } else if (color == "blue") { + digitalWrite(PinRED, LOW); + digitalWrite(PinGREEN, LOW); + digitalWrite(PinBLUE, HIGH); + } else if (color == "yellow") { // Rot + Grün + digitalWrite(PinRED, HIGH); + digitalWrite(PinGREEN, HIGH); + digitalWrite(PinBLUE, LOW); + } else if (color == "cyan") { // Grün + Blau + digitalWrite(PinRED, LOW); + digitalWrite(PinGREEN, HIGH); + digitalWrite(PinBLUE, HIGH); + } else if (color == "pink") { // Rot + Blau (auch Magenta) + digitalWrite(PinRED, HIGH); + digitalWrite(PinGREEN, LOW); + digitalWrite(PinBLUE, HIGH); + } else if (color == "white") { // Alle Farben + digitalWrite(PinRED, HIGH); + digitalWrite(PinGREEN, HIGH); + digitalWrite(PinBLUE, HIGH); + } else if (color == "off") { // LED aus + digitalWrite(PinRED, LOW); + digitalWrite(PinGREEN, LOW); + digitalWrite(PinBLUE, LOW); + } else { + Serial.println("Unbekannte Farbe: " + color); + } +} + + +// Funktion, um zu einem der Netzwerke zu verbinden +void connectToWiFi() { + + Serial.println("WLAN Verbindungsaufbau zu: " + String(ssidList[current_ap])); + + + // Verbinde mit dem aktuellen AP (SSID und Passwort aus den Arrays) + WiFi.begin(ssidList[current_ap], passwordList[current_ap]); + + // Warte auf die Verbindung + int attempt = 0; + while (WiFi.status() != WL_CONNECTED && attempt < 10) { + led_set_color("cyan"); + Serial.print("."); // Punkt ausgeben, um anzuzeigen, dass es versucht, sich zu verbinden + delay(500); + led_set_color("off"); + Serial.print("."); // Punkt ausgeben, um anzuzeigen, dass es versucht, sich zu verbinden + delay(500); + attempt++; + } + + // Wenn keine Verbindung hergestellt werden konnte, wechsle zum nächsten Netzwerk + if (WiFi.status() != WL_CONNECTED) { + WiFi.disconnect(); + delay(500); + Serial.println(""); + Serial.println("Verbindung fehlgeschlagen."); + current_ap = (current_ap + 1) % numNetworks; // Wechsel zur nächsten SSID, nach der letzten wieder zur ersten + reconnecting = false; // Zurücksetzen des Flags, falls alle Netzwerke fehlgeschlagen sind + } + else { + Serial.print("\nWLAN verbunden: "); + Serial.print(WiFi.SSID()); + Serial.print(" "); + Serial.println(WiFi.RSSI()); + + reconnecting = false; // Verbindung erfolgreich, setze reconnecting zurück + + } + +} + +// Funktion zum Extrahieren des Wertes aus der XML-Antwort +String extractValue(const String& url) { + WiFiClient client; // WiFiClient-Objekt erstellen + HTTPClient http; + + http.begin(client, url); // WiFiClient und URL übergeben + + int httpResponseCode = http.GET(); + if (httpResponseCode > 0) { + String response = http.getString(); + Serial.println("Antwort: " + response); + + int startIndex = response.indexOf("value='"); + if (startIndex == -1) { + http.end(); // Verbindung schließen + return ""; + } + + startIndex += 7; // Länge von "value='" + int endIndex = response.indexOf("'", startIndex); + if (endIndex == -1) { + http.end(); // Verbindung schließen + return ""; + } + + http.end(); // Verbindung schließen + return response.substring(startIndex, endIndex); + } else { + Serial.println("HTTP-Fehler: " + String(httpResponseCode)); + } + + http.end(); // Verbindung schließen + return ""; +} + + + +void setup() { + Serial.begin(115200); + delay(200); + + Serial.println("Setze Pins als Ausgänge"); + pinMode(PinRED, OUTPUT); + pinMode(PinGREEN, OUTPUT); + pinMode(PinBLUE, OUTPUT); +} + +void loop() { + + // Prüfe, ob die Verbindung verloren wurde + if (WiFi.status() != WL_CONNECTED && !reconnecting) { + Serial.println("WLAN Verbindung verloren. Versuche erneut zu verbinden..."); + reconnecting = true; // Setze Flag, dass ein Reconnectversuch läuft + connectToWiFi(); // Versuche eine neue Verbindung + } + + // Wenn alle Netzwerke durchlaufen wurden und noch keine Verbindung besteht, setze das reconnecting-Flag zurück + if (WiFi.status() != WL_CONNECTED && current_ap == 0) { + reconnecting = false; + } + + + if (WiFi.status() == WL_CONNECTED && !reconnecting) { + + + String value = extractValue(hm_sysvar_url); + Serial.println("Extrahierter Wert (Lüften sinnvoll?): " + value); + + if (value) { + led_set_color("green"); + Serial.println("Grüne LED einschalten"); + + } else { + led_set_color("red"); + Serial.println("Rote LED einschalten"); + } + + } + + delay(60000); +} diff --git a/src/settings.h b/src/settings.h new file mode 100644 index 0000000..b7faef7 --- /dev/null +++ b/src/settings.h @@ -0,0 +1,29 @@ +#ifndef SETTINGS_H +#define SETTINGS_H + +// ######################## WLAN-Daten ######################## + +const char* hostname = "ESP6288_Keller_Lueften"; + +const char* ssidList[] = { + "SSID_1", // Netzwerk 1 + "SSID_2", // Netzwerk 2 + "SSID_3" // Netzwerk 3 + // Weitere SSID hier hinzufügen +}; + +const char* passwordList[] = { + "Passwort_1", // Passwort für SSID 1 + "Passwort_2", // Passwort für SSID 2 + "Passwort_3" // Passwort für SSID 3 + // Weitere Passwörter hier hinzufügen +}; + +// ################# Homematic Systemvariable ################# + +const char* hm_sysvar_url = "http://192.168.178.50/addons/xmlapi/sysvar.cgi?sid=kYvzkyRPluLBsfLL&ise_id=20746"; + +// ############################################################ + + +#endif // SETTINGS_H diff --git a/test/README b/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html