Wenn man eine größere Anzahl von ESP8266 basierten Sensoren gebaut hat, ist es unter Umständen etwas nervig, individuelle Parameter im Arduino IDE einzutragen und dann jedes Mal die einzelnen Sensoren mit maßgeschneiderter Individual-Software zu bespielen.
Das gilt um so mehr, wenn man zusätzlich MQTT Parameter eintragen muss oder die Dinger in anderen – ggf. im Voraus nicht bekannten – WiFi Netzen einsetzen will. Hat man ein schönes Gehäuse gebastelt oder den Controller sonstwie verbaut, ist es doppelt nervig.
Ich habe mir verschiedene Lösungen angeschaut, den ESP8266 ohne Neu-Programmieren ins Netz zu bringen – von easy bis komplex :
Update Mai 2024: Durch verschiedene andere Projekte habe ich das IDE auf die Version 2 umgestellt und dabei notgedrungenermaßen einige neue Libraries installiert. Das hatte dann zur Folge, dass meine unten stehenden Sketches nicht mehr funktionierten – das heißt nach dem Einstellen der Credentials ist der Sketch genau einmal durchgelaufen und dann nicht mehr. Nach vielem Rumprobieren habe ich das Problem gelöst, indem ich den Connect explizit mit einem WiFi.begin(); gestartet habe. Die Stelle ist in den Sketches farblich hervorgehoben und kommentiert. Jetzt funktioniert auch die neueste Version des WiFiManagers (2.0.17).
Inhalt
1 – WiFi Setup mit WPS
Der schon verschiedentlich erwähnte Distributor AZ-Deliveries in Deggendorf gibt sich einige Mühe, die Nutzer seiner Produkte mit Anleitungen und Tipps zu versorgen – herzlichen Dank dafür!
Willst Du nur deine WiFi Anmeldedaten wie PSK und SSID flexibel erfassen, ohne den Sketch neu zu kompilieren, dann hilft dir diese gut gemachte Anleitung weiter.
Über einen angeschlossenen Button wird die WPS Routine gestartet, drückt man dann noch die WPS Taste am Router, werden die Daten automatisch übertragen und in einem besonderen Speicherbereich des Controllers abgelegt.
Leider kann ich damit nur die WiFi Einstellungen vornehmen. Andere Daten müssen nach wie vor programmiert werden. Hat man keinen physischen oder administrativen Zugriff auf den Router, hilft die Anleitung leider nichts!
2 – Konfiguration mit der WiFi Manager Library
Einen großen Schritt weiter geht die geniale WiFi Manager Library, die wir in unser IDE einspielen können.
Sie stellt einen temporären Konfigurations Accesspoint (Captive Portal) mit Webserver, Konfigurationsdialog und WiFi Parameter Handling zur Verfügung. Und nicht nur das. Es lassen sich auch weitere Daten interaktiv eintragen, die im Controller EEPROM hinterlegt werden und sich später programmgesteuert verwenden lassen. Bei mir sind das der MQTT Server, der dazugehörige Username, das MQTT Passwort und die MQTT Topics (Pfade), die ich für die Ablage meiner Messwerte brauche.
Abbildung 1: WiFi Manager Startseite
Abbildung 2: Konfigurationsseite mit Erweiterung für MQTT Parameter.
Zum Starten der Konfiguration gibt es wiederum mehrere Möglichkeiten:
2a – Konfiguration nur, wenn keine Verbindung zum WLAN
Hat man den Controller in eine "fremde Umgebung" gebracht und schaltet den Sensor (oder whatever) ein, kann er sich notgedrungen nicht mit dem bekannten WLAN connecten und startet deshalb den Accesspoint zur Konfiguration. Mit einem Smartfone, Tablet oder PC kann man das temporär aufgespannte Netz suchen – bei mir heißt es "RustiSensor" sonst eigentlich "OnDemandAP". Nach dem Verbinden wird (zumindest bei Apple Endgeräten) automatisch die Konfigurationsseite aufgerufen. Falls nicht, mit dem Browser einfach zu 192.168.4.1 navigieren.
Die Basics findet ihr auf der Github Seite des WiFi Manager Autors: https://github.com/tzapu/WiFiManager. Dort findet sich auch eine Reihe von sehr schönen Anwendungsbeispielen.
Überhaupt auf die Idee gebracht wurde ich von Rui Santos aus Portugal, der eine hervorragende, englischsprachige Site namens randomnerdtutorials.com betreibt und auch viele kostenpflichtigen Tutorials zum Arduino, ESP8266 und ESP32 anbietet. Der eigentliche – kostenlose – Beitrag befindet sich hinter diesem Link.
Von ihm habe ich auch die Code Snippets für die Verwendung von JSON zur Verarbeitung der abgelegten Parameter. Sein Beitrag ist schon etwas älter und verwendet die JSON Bibliothek der Version 5.x.x. Neuer wäre die Version 6.x.x., aber die ist von der Syntax her nicht kompatibel. Ich habe deshalb im Library Manager die höchstverfügbare 5er Version 5.13.5 ausgewählt.
Abbildung 3: Auswahl älterer Library Version
Alternativ könnte man auch den Code auf Bibliotheksversion 6.x.x umschreiben oder ein ganz eigenes Stringhandling im Code einbauen – z.B. durch Zusammenfassen und Wegspeichern der Extradaten in einem langen String bzw. umgekehrt.
Nebenbei bemerkt: das String bzw. Char Array Handling des Arduino C Dialekts ist richtig grottig. Sowas von unkomfortabel. Python ist da wesentlich einfacher.
Ferner habe ich das neuere LittleFS anstatt SPIFFS zum Speichern der Daten im EEPROM verwendet. Die Compilerwarnungen "…deprecated…" haben zu sehr genervt.
Der Sketch
Für diejenigen, die es interessiert, hier noch der von mir – mit Leihgaben – produzierte Code für einen DHT22 Sensor und MQTT auf Basis eines D1 Mini Controllers. Alle Routinen stecken im Setup {} Bereich, da der Sketch nur einmal durchläuft, anschließend den Controller schlafen legt, um nach dem Aufwachen wieder von vorne anzufangen.
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 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
/********* Credits: WiFi Manager Library und allgemeines Vorgehen: https://github.com/tzapu/WiFiManager Rui Santos: JSON Routine für Parameterspeicherung - JSON Library muss < v6 sein! project details at http://randomnerdtutorials.com Mit LittleFS realisiert anstatt SPIFFS Beim Start versucht ESP 8266zu connecten, wenn kein WLAN gefunden, dann Start Captive Portal zur Konfiguration von SSID, PSK, MQTT Server, Username, Topic Pfade *********/ #include <LittleFS.h> //this needs to be first, or it all crashes and burns... #include <ESP8266WiFi.h> #include <DNSServer.h> #include <ESP8266WebServer.h> #include <WiFiManager.h> // https://github.com/tzapu/WiFiManager #include <ArduinoJson.h> // https://github.com/bblanchon/ArduinoJson #include "DHT_U.h" #include <MQTT.h> #define DHTTYPE DHT22 #define DHTPIN 14 // Set web server port number to 80 WiFiServer server(80); WiFiClient net; MQTTClient mqtt; DHT dht(DHTPIN, DHTTYPE); char mqtt_server[15] = "IP Adresse"; char mqtt_user[20] = "MQTT User"; char mqtt_password[20] = "MQTT Password"; char mqtt_pathtemp[40] = "/Pfad/Temperatur"; char mqtt_pathhum[40] = "/Pfad/Luftfeuchtigkeit"; int MaxReconnects = 5; // Max Anzahl MQTT Server Verbindungsversuche int MQTTReconnects = 0; // Zähler für MQTT Reconnects int WiFiConnRetry=0; // Zähler für WiFi Connect Retrys int WiFiConnMax=100; // Max Anzahl WiFi Verbindungsversuche //flag for saving data bool shouldSaveConfig = false; //callback notifying us of the need to save config void saveConfigCallback () { Serial.println("Should save config"); shouldSaveConfig = true; } void setup() { Serial.begin(115200); Serial.println(); Serial.println("Booting..."); //clean FS, for testing //LittleFS.format(); //read configuration from FS json Serial.println("mounting FS..."); if (LittleFS.begin()) { Serial.println("mounted file system"); if (LittleFS.exists("/config.json")) { //file exists, reading and loading Serial.println("reading config file"); File configFile = LittleFS.open("/config.json", "r"); if (configFile) { Serial.println("opened config file"); size_t size = configFile.size(); // Allocate a buffer to store contents of the file. std::unique_ptr<char[]> buf(new char[size]); configFile.readBytes(buf.get(), size); DynamicJsonBuffer jsonBuffer; JsonObject& json = jsonBuffer.parseObject(buf.get()); json.printTo(Serial); if (json.success()) { Serial.println("\nparsed json"); strcpy(mqtt_server, json["mqtt_server"]); strcpy(mqtt_user, json["mqtt_user"]); strcpy(mqtt_password, json["mqtt_password"]); strcpy(mqtt_pathtemp, json["mqtt_pathtemp"]); strcpy(mqtt_pathhum, json["mqtt_pathhum"]); } else { Serial.println("failed to load json config"); } } } } else { Serial.println("failed to mount FS"); } //end read WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 15); WiFiManagerParameter custom_mqtt_user("user", "mqtt user", mqtt_user, 20); WiFiManagerParameter custom_mqtt_password("password", "mqtt password", mqtt_password, 20); WiFiManagerParameter custom_mqtt_pathtemp("pathtemp", "mqtt path temp", mqtt_pathtemp, 40); WiFiManagerParameter custom_mqtt_pathhum("pathhum", "mqtt path hum", mqtt_pathhum, 40); // WiFiManager // Local intialization. Once its business is done, there is no need to keep it around WiFiManager wifiManager; //set config save notify callback wifiManager.setSaveConfigCallback(saveConfigCallback); // set custom ip for portal //wifiManager.setAPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0)); //add all your parameters here wifiManager.addParameter(&custom_mqtt_server); wifiManager.addParameter(&custom_mqtt_user); wifiManager.addParameter(&custom_mqtt_password); wifiManager.addParameter(&custom_mqtt_pathtemp); wifiManager.addParameter(&custom_mqtt_pathhum); // Uncomment and run it once, if you want to erase all the stored information //wifiManager.resetSettings(); //set minimum quality of signal so it ignores AP's under that quality //defaults to 8% //wifiManager.setMinimumSignalQuality(); //sets timeout until configuration portal gets turned off //useful to make it all retry or go to sleep //in seconds wifiManager.setTimeout(180); // fetches ssid and pass from eeprom and tries to connect // if it does not connect it starts an access point with the specified name // here "AutoConnectAP" // and goes into a blocking loop awaiting configuration // wifiManager.autoConnect("RustiSensor"); // Normale Routine // or use this for auto generated name ESP + ChipID // wifiManager.autoConnect(); // Start WiFi Manager mit Timeout Überprüfung. Nach Timeout... Tiefschlaf if (!wifiManager.autoConnect("RustiSensor")) { Serial.println("failed to connect and hit timeout"); delay(3000); //reset and try again, or maybe put it to deep sleep ESP.deepSleep(0); // sleep forever } // if you get here you have connected to the WiFi Serial.println("Connected."); strcpy(mqtt_server, custom_mqtt_server.getValue()); strcpy(mqtt_user, custom_mqtt_user.getValue()); strcpy(mqtt_password, custom_mqtt_password.getValue()); strcpy(mqtt_pathtemp, custom_mqtt_pathtemp.getValue()); strcpy(mqtt_pathhum, custom_mqtt_pathhum.getValue()); Serial.println("saved MQTT params:"); Serial.println(mqtt_server); Serial.println(mqtt_user); Serial.println(mqtt_password); Serial.println(mqtt_pathtemp); Serial.println(mqtt_pathhum); //save the custom parameters to FS if (shouldSaveConfig) { Serial.println("saving config"); DynamicJsonBuffer jsonBuffer; JsonObject& json = jsonBuffer.createObject(); json["mqtt_server"] = mqtt_server; json["mqtt_user"] = mqtt_user; json["mqtt_password"] = mqtt_password; json["mqtt_pathtemp"] = mqtt_pathtemp; json["mqtt_pathhum"] = mqtt_pathhum; LittleFS.format(); // weiss nicht, ob das nötig ist, schadet aber nicht. File configFile = LittleFS.open("/config.json", "w"); if (!configFile) { Serial.println("failed to open config file for writing"); } json.printTo(Serial); json.printTo(configFile); configFile.close(); //end save } WiFi.softAPdisconnect (true); // turns off Access Point visibility in net neighbourhood //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //++++++++++++++++++++++++Sensor activity & MQTT publishing++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //WiFi.begin(ssid, password); // not needed! WiFi Manager's job! WiFi.begin(); // Unter Umständen erforderlich wenn der D1 Mini nicht connected // Nachfolgende WHILE Schleife wird benötigt, um sauber mit dem Router zu connecten. // Insbesondere die Fritz!Box hat sonst manchmal Probleme beim Aufwachen aus dem Stromsparmodus. while (WiFi.status() != WL_CONNECTED) { delay(100); Serial.print("."); WiFiConnRetry++; if (WiFiConnRetry >= WiFiConnMax){ Serial.println("No WiFi Connect, sleep 30 mins"); delay(1000); ESP.deepSleep(1800e6); } } mqtt.begin(mqtt_server, net); mqtt.loop(); delay(10); while (!mqtt.connect(mqtt_server, mqtt_user, mqtt_password)) { Serial.print("MQTT connect "); Serial.println(MQTTReconnects); MQTTReconnects++; if (MQTTReconnects > MaxReconnects) { Serial.println("No MQTT Connect, going to sleep"); delay(1000); ESP.deepSleep(1800e6); //30 Minuten } delay(500); } Serial.println("MQTT connection established!"); dht.begin(); delay(2000); float temp = dht.readTemperature(); float humidity = dht.readHumidity(); Serial.print("MQTT Status: "); Serial.println(mqtt.connected()); Serial.print("Sending... "); Serial.println(); if (!isnan(humidity) || !isnan(temp)) { Serial.print("Temp: "); Serial.print(String(temp)); Serial.print(" Humidity: "); Serial.println(String(humidity)); mqtt.publish(String(mqtt_pathtemp), String(temp)); mqtt.publish(String(mqtt_pathhum), String(humidity)); mqtt.disconnect(); } Serial.println("Going into deep sleep for xx seconds"); ESP.deepSleep(1800e6); // e.g. 20e6 is 20 seconds } void loop() {} |
Für viele Fälle reicht das. Nachteil ist natürlich, dass man nicht so ohne Weiteres an die MQTT Parameter herankommt, wenn man sie einmal gespeichert hat. Entweder geht man mit dem Microcontroller und dessen Stromversorgung nach draußen, wo es keinen Empfang gibt oder man schaltet das WLAN kurz ab – in beiden Fällen würde dann das so genannte "Captive Portal" aufgerufen. Vorteil dieser Lösung ist, dass man keine zusätzliche Hardware verlöten muss.
2b – Konfiguration mit Button starten
Elegant wäre es, wenn man die Konfiguration per Knopfdruck starten könnte – ganz ähnlich wie bei den professionellen Sensoren à la Shelly. Hierzu liefert der Autor des WiFi Managers ein schönes Beispiel, das ich entsprechend modifiziert habe. Im Original ist die Routine im Loop{} Bereich untergebracht und kann jederzeit mittels Knopfdruck gestartet werden.
Da mein Sensor ja die Loop{} Schleife nicht nutzt und immer nur ein paar Sekunden aktiv ist, habe ich die entsprechenden Kommandos in den Setup{} Bereich gepackt und mit der Buttonabfrage versehen.
Der Button wird an einem freien GPIO Pin des Controllers angeschlossen und zieht beim Drücken den Pin auf Low – also gegen Masse. Ein Fritzing Diagramm dafür findet ihr weiter unten.
Ich habe aus bautechnischen Gründen den Pin D4 bzw GPIO 2 verwendet. Die Platine aus dem letzten D1 Mini Beitrag habe ich entspreched angepasst und einen Drucktaster auf der Rückseite der Trägerplatine zwischen D4 und GND eingelötet.
Abbildung 4: Rückseite mit eingelötetem Button
Die Stromversorgung erfolgt mittels vier AA Akkus, die nominell 4,8 V liefern und somit an den 5V Anschlusspin gelötet werden. Dieser verträgt Spannungen von 3 bis 7V
Der Sketch
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 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 |
/********* Credits: WiFi Manager Library und allgemeines Vorgehen: https://github.com/tzapu/WiFiManager Rui Santos: JSON Routine für Sparameterspeicherung - JSON Library muss < v6 sein! project details at http://randomnerdtutorials.com Mit LittleFS realisiert anstatt SPIFFS Nach dem Starten oder einem Reset hat der User ca. 3 Sekunden Zeit, den Config- Button zu drücken. Der Controller geht dann in den Setup Modus. Achtung: Es muss in jedem Fall ein Wifi Passwort (PSK) eingegeben werden, damit geänderte Daten gespeichert werden. *********/ #include <LittleFS.h> //this needs to be first, or it all crashes and burns... #include <ESP8266WiFi.h> #include <DNSServer.h> #include <ESP8266WebServer.h> #include <WiFiManager.h> // https://github.com/tzapu/WiFiManager #include <ArduinoJson.h> // https://github.com/bblanchon/ArduinoJson #include "DHT_U.h" #include <MQTT.h> #define DHTTYPE DHT22 #define DHTPIN 14 // select which pin will trigger the configuration portal when set to LOW #define TRIGGER_PIN 2 // Set web server port number to 80 WiFiServer server(80); WiFiClient net; MQTTClient mqtt; DHT dht(DHTPIN, DHTTYPE); char mqtt_server[15] = "IP Adresse"; char mqtt_user[20] = "MQTT User"; char mqtt_password[20] = "MQTT Password"; char mqtt_pathtemp[40] = "/Pfad/Temperatur"; char mqtt_pathhum[40] = "/Pfad/Luftfeuchtigkeit"; int MaxReconnects = 5; // Max Anzahl MQTT Server Verbindungsversuche int MQTTReconnects = 0; // Zähler für MQTT Reconnects int WiFiConnRetry=0; // Zähler für WiFi Connect Retrys int WiFiConnMax=100; // Max Anzahl WiFi Verbindungsversuche int loopctr = 0; //Zähler Schleifendurchläufe - Warten auf Triggger bool keypressed = false; //flag for saving data bool shouldSaveConfig = false; //callback notifying us of the need to save config void saveConfigCallback () { Serial.println("Should save config"); shouldSaveConfig = true; } void setup() { Serial.begin(115200); Serial.println(); Serial.println("Booting..."); //Blinker pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); //clean FS, for testing //LittleFS.format(); //read configuration from FS json Serial.println("mounting FS..."); if (LittleFS.begin()) { Serial.println("mounted file system"); if (LittleFS.exists("/config.json")) { //file exists, reading and loading Serial.println("reading config file"); File configFile = LittleFS.open("/config.json", "r"); if (configFile) { Serial.println("opened config file"); size_t size = configFile.size(); // Allocate a buffer to store contents of the file. std::unique_ptr<char[]> buf(new char[size]); configFile.readBytes(buf.get(), size); DynamicJsonBuffer jsonBuffer; JsonObject& json = jsonBuffer.parseObject(buf.get()); json.printTo(Serial); if (json.success()) { Serial.println("\nparsed json"); strcpy(mqtt_server, json["mqtt_server"]); strcpy(mqtt_user, json["mqtt_user"]); strcpy(mqtt_password, json["mqtt_password"]); strcpy(mqtt_pathtemp, json["mqtt_pathtemp"]); strcpy(mqtt_pathhum, json["mqtt_pathhum"]); } else { Serial.println("failed to load json config"); } } } } else { Serial.println("failed to mount FS"); } //end read WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 15); WiFiManagerParameter custom_mqtt_user("user", "mqtt user", mqtt_user, 20); WiFiManagerParameter custom_mqtt_password("password", "mqtt password", mqtt_password, 20); WiFiManagerParameter custom_mqtt_pathtemp("pathtemp", "mqtt path temp", mqtt_pathtemp, 40); WiFiManagerParameter custom_mqtt_pathhum("pathhum", "mqtt path hum", mqtt_pathhum, 40); //Schleife zum Erkennen, ob Trigger aktiv while (!keypressed && loopctr < 3) { if ( digitalRead(TRIGGER_PIN) == LOW ) { keypressed = true; Serial.println("Key pressed!!"); } delay(1000); //Serial.println(loopctr); loopctr++; } // WiFiManager nur, wenn Trigger vorher aktiviert wurde if (keypressed) { blink(100, 200, 5); // Local intialization. Once its business is done, there is no need to keep it around WiFiManager wifiManager; //set config save notify callback wifiManager.setSaveConfigCallback(saveConfigCallback); //add all your parameters here wifiManager.addParameter(&custom_mqtt_server); wifiManager.addParameter(&custom_mqtt_user); wifiManager.addParameter(&custom_mqtt_password); wifiManager.addParameter(&custom_mqtt_pathtemp); wifiManager.addParameter(&custom_mqtt_pathhum); // erase all the stored information wifiManager.resetSettings(); //set minimum quality of signal so it ignores AP's under that quality //defaults to 8% //wifiManager.setMinimumSignalQuality(); //sets timeout until configuration portal gets turned off //useful to make it all retry or go to sleep //in seconds wifiManager.setTimeout(180); // fetches ssid and pass from eeprom and tries to connect // if it does not connect it starts an access point with the specified name // here "AutoConnectAP" // and goes into a blocking loop awaiting configuration // wifiManager.autoConnect("RustiSensor"); // Normale Routine // or use this for auto generated name ESP + ChipID // wifiManager.autoConnect(); // Start WiFi Manager mit Timeout Überprüfung. Nach Timeout... Tiefschlaf if (!wifiManager.startConfigPortal("RustiSensor")) { Serial.println("failed to connect and hit timeout"); delay(3000); //reset and try again, or maybe put it to deep sleep ESP.deepSleep(0); // sleep forever } // if you get here you have connected to the WiFi Serial.println("Connected."); strcpy(mqtt_server, custom_mqtt_server.getValue()); strcpy(mqtt_user, custom_mqtt_user.getValue()); strcpy(mqtt_password, custom_mqtt_password.getValue()); strcpy(mqtt_pathtemp, custom_mqtt_pathtemp.getValue()); strcpy(mqtt_pathhum, custom_mqtt_pathhum.getValue()); Serial.println("saved MQTT params:"); Serial.println(mqtt_server); Serial.println(mqtt_user); Serial.println(mqtt_password); Serial.println(mqtt_pathtemp); Serial.println(mqtt_pathhum); Serial.print("Should save---->"); Serial.println(shouldSaveConfig); //save the custom parameters to FS if (shouldSaveConfig) { Serial.println("saving config"); DynamicJsonBuffer jsonBuffer; JsonObject& json = jsonBuffer.createObject(); json["mqtt_server"] = mqtt_server; json["mqtt_user"] = mqtt_user; json["mqtt_password"] = mqtt_password; json["mqtt_pathtemp"] = mqtt_pathtemp; json["mqtt_pathhum"] = mqtt_pathhum; LittleFS.format(); // weiss nicht, ob das nötig ist, schadet aber nicht. File configFile = LittleFS.open("/config.json", "w"); if (!configFile) { Serial.println("failed to open config file for writing"); } json.printTo(Serial); json.printTo(configFile); configFile.close(); //end save } } WiFi.softAPdisconnect (true); // turns off Access Point visibility in net neighbourhood //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //++++++++++++++++++++++++Sensor activity & MQTT publishing++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //WiFi.begin(ssid, password); // not needed! WiFi Manager's job! WiFi.begin(); // bei neueren Versionen der Libraries erforderlich wenn D1 Mini nicht connecten will // Nachfolgende WHILE Schleife wird benötigt, um sauber mit dem Router zu connecten. // Insbesondere die Fritz!Box hat manchmal Probleme beim Aufwachen aus dem Stromsparmodus. while (WiFi.status() != WL_CONNECTED) { delay(100); Serial.print("."); WiFiConnRetry++; if (WiFiConnRetry >= WiFiConnMax){ Serial.println("No WiFi Connect, sleep 30 mins"); delay(1000); ESP.deepSleep(1800e6); } } mqtt.begin(mqtt_server, net); mqtt.loop(); delay(10); while (!mqtt.connect(mqtt_server, mqtt_user, mqtt_password)) { Serial.print("MQTT connect "); Serial.println(MQTTReconnects); ++MQTTReconnects; if (MQTTReconnects > MaxReconnects) { blink(250, 200, 3); //"S" delay(1500); blink(1000, 200, 3); //"O" delay(1500); blink(250, 200, 3); //"S" Serial.println("No MQTT Connect, going to sleep"); delay(1000); ESP.deepSleep(1800e6); } delay(500); } Serial.println("MQTT connection established!"); dht.begin(); delay(2000); float temp = dht.readTemperature(); float humidity = dht.readHumidity(); Serial.print("MQTT Status: "); Serial.println(mqtt.connected()); Serial.print("Sending... "); Serial.println(); if (!isnan(humidity) || !isnan(temp)) { Serial.print("Temp: "); Serial.print(String(temp)); Serial.print(" Humidity: "); Serial.println(String(humidity)); mqtt.publish(String(mqtt_pathtemp), String(temp)); mqtt.publish(String(mqtt_pathhum), String(humidity)); mqtt.disconnect(); } Serial.println("Going into deep sleep for xx seconds"); ESP.deepSleep(1885e6); // e.g. 20e6 is 20 seconds } void loop() {} void blink(int t1, int t0, int n) { // Schaltet LED ein und aus. Übergabeparameter: Millisekunden Ein, // Millisekunden aus, Anzahl Blinks // Optional - ggf. weglassen, um Strom zu sparen int b = 0; while (b <= n) { digitalWrite(LED_BUILTIN, LOW); delay(t1); digitalWrite(LED_BUILTIN, HIGH); delay(t0); b++; } } |
Funktioniert schon ganz gut. Ein Nachteil ist allerdings, dass die geänderten Daten nur dann gespeichert werden, wenn man auch die SSID und das WLAN Passwort (PSK) wieder einträgt.
Abbildung 5: Versuchsaufbau auf Breadboard
Abbidung 6: Fritzing Diagramm (Reset Verbindung zwischen D0 und RST – grün – Jumper)
Wenn ihr tiefer einsteigen wollt, kann ich euch das Kapitel über den D1 Mini in Wolles Elektronikkiste nur wärmstens empfehlen!
Wie immer: Fragen oder Kritik sind erwünscht – Kommentarfunktion.
Hi,
wen es interessiert, beim WifiManager liegt ein noch nicht umgesetzter Pull-Request für die ArduinoJSON V 6 rum:
https://github.com/tzapu/WiFiManager/pull/1060/commits/b22ba24283ad3f22f8c8dfb2a52ed0583c0222d7
Da dieses HowTo auf dem Example basiert kann man es recht schnell abändern…
Schönen Gruß
Vielen Dank für die Info. Hoffen wir mal, dass sich jemand erbarmt und das umsetzt.
VG Chris
Hallo
genau das hab ich schon lange gesucht ! Bin 71 Jahre jung und versuche meine grauen Zellen in Schuss zu halten, lerne begierig Alles zum Thema IOT.
Betreibe auch ca 12 ESP8266 Mini D1 und andere boards mit meinem Netzwerk /Mosquitto und Node red .
Ich habe den ersten Scetch, meine Arduino IDE compilieren lassen
und nach Änderung auf die V5.x .Json-version wird bei mir der Code auch fehlerfrei bis auf folgenden
Eintrag übersetzt :
exit status 1
'MQTTClient' does not name a type
Was kann, sollte ich andern ?
Vielen Dank im Vorraus
Martin
Hallo,
ja Programmieren hält die grauen Zellen frisch.
Zu deinem Problem: Könnte es sein, dass du die MQTT Library noch nicht installiert hast? https://github.com/256dpi/arduino-mqtt
Oder über Werkzeuge–>Bibliotheken verwalten–> in Suchfeld rechts oben MQTT eingeben und nachher die Library MQTT by Joel Gaehwiler auswählen.
Viel Glück und weiter viele gelungene Projekte.
Chris