{"id":1455,"date":"2020-12-03T16:41:06","date_gmt":"2020-12-03T15:41:06","guid":{"rendered":"https:\/\/www.rustimation.eu\/?p=1455"},"modified":"2024-05-16T13:13:34","modified_gmt":"2024-05-16T11:13:34","slug":"esp8266-wifi-parameter-speichern","status":"publish","type":"post","link":"https:\/\/www.rustimation.eu\/index.php\/esp8266-wifi-parameter-speichern\/","title":{"rendered":"ESP8266: WiFi Passwort etc. ohne Programmieren speichern"},"content":{"rendered":"<p>Wenn man eine gr\u00f6\u00dfere Anzahl von ESP8266 basierten Sensoren gebaut hat, ist es unter Umst\u00e4nden etwas nervig, individuelle Parameter im Arduino IDE einzutragen und dann jedes Mal die einzelnen Sensoren mit ma\u00dfgeschneiderter Individual-Software zu bespielen.<\/p>\n<p>Das gilt um so mehr, wenn man zus\u00e4tzlich MQTT Parameter eintragen muss oder die Dinger in anderen &#8211; ggf. im Voraus nicht bekannten &#8211; WiFi Netzen einsetzen will. Hat man ein sch\u00f6nes Geh\u00e4use gebastelt oder den Controller sonstwie verbaut, ist es doppelt nervig.<\/p>\n<p>Ich habe mir verschiedene L\u00f6sungen angeschaut, den ESP8266 ohne Neu-Programmieren ins Netz zu bringen &#8211; von easy bis komplex :<\/p>\n<p><!--more--><\/p>\n<p><strong>Update Mai 2024:<\/strong> Durch verschiedene <a href=\"https:\/\/www.rustimation.eu\/index.php\/solar-pylontech-akku-ueber-konsole-aufwecken\/\" target=\"_blank\" rel=\"noopener\">andere Projekte<\/a> habe ich das IDE auf die Version 2 umgestellt und dabei notgedrungenerma\u00dfen einige neue Libraries installiert. Das hatte dann zur Folge, dass meine unten stehenden Sketches nicht mehr funktionierten &#8211; das hei\u00dft nach dem Einstellen der Credentials ist der Sketch genau einmal durchgelaufen und dann nicht mehr. Nach vielem Rumprobieren habe ich das Problem gel\u00f6st, indem ich den Connect explizit mit einem <span class=\"lang:c++ decode:true crayon-inline \"> WiFi.begin();<\/span> gestartet habe. Die Stelle ist in den Sketches farblich hervorgehoben und kommentiert. Jetzt funktioniert auch die neueste Version des WiFiManagers (2.0.17).<\/p>\n<h3>1 &#8211; WiFi Setup mit WPS<\/h3>\n<p>Der schon verschiedentlich erw\u00e4hnte Distributor AZ-Deliveries in Deggendorf gibt sich einige M\u00fche, die Nutzer seiner Produkte mit Anleitungen und Tipps zu versorgen &#8211; herzlichen Dank daf\u00fcr!<\/p>\n<p>Willst Du nur deine WiFi Anmeldedaten wie PSK und SSID flexibel erfassen, ohne den Sketch neu zu kompilieren, dann hilft dir diese <a href=\"https:\/\/www.az-delivery.de\/blogs\/azdelivery-blog-fur-arduino-und-raspberry-pi\/wps-mit-dem-esp8266\">gut gemachte Anleitung<\/a> weiter.<\/p>\n<p>\u00dcber einen angeschlossenen Button wird die WPS Routine gestartet, dr\u00fcckt man dann noch die WPS Taste am Router, werden die Daten automatisch \u00fcbertragen und in einem besonderen Speicherbereich des Controllers abgelegt.<\/p>\n<p>Leider kann ich damit nur die WiFi Einstellungen vornehmen. Andere Daten m\u00fcssen nach wie vor programmiert werden. Hat man keinen physischen oder administrativen Zugriff auf den Router, hilft die Anleitung leider nichts!<\/p>\n<h3>2 &#8211; Konfiguration mit der WiFi Manager Library<\/h3>\n<p>Einen gro\u00dfen Schritt weiter geht die geniale WiFi Manager Library, die wir in unser IDE einspielen k\u00f6nnen.<\/p>\n<figure id=\"attachment_1501\" aria-describedby=\"caption-attachment-1501\" style=\"width: 864px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-1501 size-full\" src=\"https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/ArduinoJSON-1-e1608122973351.jpg\" alt=\"\" width=\"864\" height=\"499\" srcset=\"https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/ArduinoJSON-1-e1608122973351.jpg 864w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/ArduinoJSON-1-e1608122973351-300x173.jpg 300w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/ArduinoJSON-1-e1608122973351-768x444.jpg 768w\" sizes=\"auto, (max-width: 864px) 100vw, 864px\" \/><figcaption id=\"caption-attachment-1501\" class=\"wp-caption-text\">Library Manager des alten Arduino IDE<\/figcaption><\/figure>\n<p>Sie stellt einen tempor\u00e4ren Konfigurations Accesspoint (Captive Portal) mit Webserver, Konfigurationsdialog und WiFi Parameter Handling zur Verf\u00fcgung. Und nicht nur das. Es lassen sich auch weitere Daten interaktiv eintragen, die im Controller EEPROM hinterlegt werden und sich sp\u00e4ter programmgesteuert verwenden lassen. Bei mir sind das der MQTT Server, der dazugeh\u00f6rige Username, das MQTT Passwort und die MQTT Topics (Pfade), die ich f\u00fcr die Ablage meiner Messwerte brauche.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1457 size-large\" src=\"https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/IMG_0735-e1607001380281-1024x761.png\" alt=\"\" width=\"604\" height=\"449\" srcset=\"https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/IMG_0735-e1607001380281-1024x761.png 1024w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/IMG_0735-e1607001380281-300x223.png 300w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/IMG_0735-e1607001380281-768x571.png 768w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/IMG_0735-e1607001380281.png 1536w\" sizes=\"auto, (max-width: 604px) 100vw, 604px\" \/><em>Abbildung 1: WiFi Manager Startseite<\/em><\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1462 size-large\" src=\"https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/IMG_0736-1-768x1024.png\" alt=\"\" width=\"604\" height=\"805\" srcset=\"https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/IMG_0736-1-768x1024.png 768w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/IMG_0736-1-225x300.png 225w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/IMG_0736-1-1152x1536.png 1152w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/IMG_0736-1.png 1536w\" sizes=\"auto, (max-width: 604px) 100vw, 604px\" \/><em>Abbildung 2: Konfigurationsseite mit Erweiterung f\u00fcr MQTT Parameter.<\/em><\/p>\n<p>Zum Starten der Konfiguration gibt es wiederum mehrere M\u00f6glichkeiten:<\/p>\n<h4>2a &#8211; Konfiguration nur, wenn keine Verbindung zum WLAN<\/h4>\n<p>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\u00e4r aufgespannte Netz suchen &#8211; bei mir hei\u00dft es \"RustiSensor\" sonst eigentlich \"OnDemandAP\".\u00a0 Nach dem Verbinden wird (zumindest bei Apple Endger\u00e4ten) automatisch die Konfigurationsseite aufgerufen. Falls nicht, mit dem Browser einfach zu 192.168.4.1 navigieren.<\/p>\n<p>Die Basics findet ihr auf der Github Seite des WiFi Manager Autors: <a href=\"https:\/\/github.com\/tzapu\/WiFiManager\">https:\/\/github.com\/tzapu\/WiFiManager. <\/a>Dort findet sich auch eine Reihe von sehr sch\u00f6nen Anwendungsbeispielen.<\/p>\n<p>\u00dcberhaupt auf die Idee gebracht wurde ich von Rui Santos aus Portugal, der eine hervorragende, englischsprachige Site namens <a href=\"https:\/\/\/randomnerdtutorials.com\">randomnerdtutorials.com<\/a> betreibt und auch viele kostenpflichtigen Tutorials zum Arduino, ESP8266 und ESP32 anbietet. Der eigentliche &#8211; kostenlose &#8211;\u00a0 Beitrag befindet sich <a href=\"https:\/\/randomnerdtutorials.com\/wifimanager-with-esp8266-autoconnect-custom-parameter-and-manage-your-ssid-and-password\/\">hinter diesem Link<\/a>.<\/p>\n<p>Von ihm habe ich auch die Code Snippets f\u00fcr die Verwendung von JSON zur Verarbeitung der abgelegten Parameter. Sein Beitrag ist schon etwas \u00e4lter und verwendet die JSON Bibliothek der Version 5.x.x. Neuer w\u00e4re die Version 6.x.x., aber die ist von der Syntax her nicht kompatibel. Ich habe deshalb im Library Manager die h\u00f6chstverf\u00fcgbare 5er Version 5.13.5 ausgew\u00e4hlt.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-1464\" src=\"https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/ArduinoJSON-1024x576.jpg\" alt=\"\" width=\"604\" height=\"340\" srcset=\"https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/ArduinoJSON-1024x576.jpg 1024w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/ArduinoJSON-300x169.jpg 300w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/ArduinoJSON-768x432.jpg 768w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/ArduinoJSON.jpg 1280w\" sizes=\"auto, (max-width: 604px) 100vw, 604px\" \/><br \/>\n<em>Abbildung 3: Auswahl \u00e4lterer Library Version<\/em><\/p>\n<p>Alternativ k\u00f6nnte man auch den Code auf Bibliotheksversion 6.x.x umschreiben oder ein ganz eigenes Stringhandling im Code einbauen &#8211; z.B. durch Zusammenfassen und Wegspeichern der Extradaten in einem langen String bzw. umgekehrt.<\/p>\n<p style=\"padding-left: 40px;\"><span style=\"color: #808080;\">Nebenbei bemerkt: das String bzw. Char Array Handling des Arduino C Dialekts ist richtig grottig. Sowas von unkomfortabel. Python ist da wesentlich einfacher.<\/span><\/p>\n<p>Ferner habe ich das neuere LittleFS anstatt SPIFFS zum Speichern der Daten im EEPROM verwendet. Die Compilerwarnungen \"&#8230;deprecated&#8230;\" haben zu sehr genervt.<\/p>\n<h5>Der Sketch<\/h5>\n<p>F\u00fcr diejenigen, die es interessiert, hier noch der von mir &#8211; mit Leihgaben &#8211; produzierte Code f\u00fcr einen<strong> DHT22 Sensor und MQTT<\/strong> auf Basis eines <em>D1 Mini<\/em> Controllers. Alle Routinen stecken im Setup {} Bereich, da der Sketch nur einmal durchl\u00e4uft, anschlie\u00dfend den Controller schlafen legt, um nach dem Aufwachen wieder von vorne anzufangen.<\/p>\n<pre class=\"height-set:true height:300 h-align:1 lang:c mark:192 decode:true\" title=\"DHT22 Sensor mit programmgesteuerer Konfiguration\">\/*********\r\n    Credits:\r\n  WiFi Manager Library und allgemeines Vorgehen: https:\/\/github.com\/tzapu\/WiFiManager\r\n  Rui Santos: JSON Routine f\u00fcr Parameterspeicherung - JSON Library muss &lt; v6 sein!\r\n              project details at http:\/\/randomnerdtutorials.com\r\n  Mit LittleFS realisiert anstatt SPIFFS\r\n\r\n  Beim Start versucht ESP 8266zu connecten, wenn kein WLAN gefunden, dann\r\n  Start Captive Portal zur Konfiguration von SSID, PSK, MQTT Server, Username, Topic Pfade\r\n*********\/\r\n\r\n#include &lt;LittleFS.h&gt; \/\/this needs to be first, or it all crashes and burns...\r\n#include &lt;ESP8266WiFi.h&gt;\r\n#include &lt;DNSServer.h&gt;\r\n#include &lt;ESP8266WebServer.h&gt;\r\n#include &lt;WiFiManager.h&gt;          \/\/ https:\/\/github.com\/tzapu\/WiFiManager\r\n#include &lt;ArduinoJson.h&gt;          \/\/ https:\/\/github.com\/bblanchon\/ArduinoJson\r\n\r\n#include \"DHT_U.h\"\r\n#include &lt;MQTT.h&gt;\r\n\r\n#define DHTTYPE DHT22\r\n#define DHTPIN 14\r\n\r\n\/\/ Set web server port number to 80\r\nWiFiServer server(80);\r\nWiFiClient net;\r\nMQTTClient mqtt;\r\n\r\nDHT dht(DHTPIN, DHTTYPE);\r\nchar mqtt_server[15] = \"IP Adresse\";\r\nchar mqtt_user[20] = \"MQTT User\";\r\nchar mqtt_password[20] = \"MQTT Password\";\r\nchar mqtt_pathtemp[40] = \"\/Pfad\/Temperatur\";\r\nchar mqtt_pathhum[40] = \"\/Pfad\/Luftfeuchtigkeit\";\r\n\r\nint MaxReconnects = 5; \/\/ Max Anzahl MQTT Server Verbindungsversuche\r\nint MQTTReconnects = 0; \/\/ Z\u00e4hler f\u00fcr MQTT Reconnects\r\nint WiFiConnRetry=0; \/\/ Z\u00e4hler f\u00fcr WiFi Connect Retrys\r\nint WiFiConnMax=100; \/\/ Max Anzahl WiFi Verbindungsversuche\r\n\r\n\/\/flag for saving data\r\nbool shouldSaveConfig = false;\r\n\r\n\/\/callback notifying us of the need to save config\r\nvoid saveConfigCallback () {\r\n  Serial.println(\"Should save config\");\r\n  shouldSaveConfig = true;\r\n}\r\n\r\nvoid setup() {\r\n  Serial.begin(115200);\r\n  Serial.println();\r\n  Serial.println(\"Booting...\");\r\n\r\n  \/\/clean FS, for testing\r\n  \/\/LittleFS.format();\r\n\r\n  \/\/read configuration from FS json\r\n  Serial.println(\"mounting FS...\");\r\n\r\n  if (LittleFS.begin()) {\r\n    Serial.println(\"mounted file system\");\r\n    if (LittleFS.exists(\"\/config.json\")) {\r\n      \/\/file exists, reading and loading\r\n      Serial.println(\"reading config file\");\r\n      File configFile = LittleFS.open(\"\/config.json\", \"r\");\r\n      if (configFile) {\r\n        Serial.println(\"opened config file\");\r\n        size_t size = configFile.size();\r\n        \/\/ Allocate a buffer to store contents of the file.\r\n        std::unique_ptr&lt;char[]&gt; buf(new char[size]);\r\n\r\n        configFile.readBytes(buf.get(), size);\r\n        DynamicJsonBuffer jsonBuffer;\r\n        JsonObject&amp; json = jsonBuffer.parseObject(buf.get());\r\n        json.printTo(Serial);\r\n        if (json.success()) {\r\n          Serial.println(\"\\nparsed json\");\r\n          strcpy(mqtt_server, json[\"mqtt_server\"]);\r\n          strcpy(mqtt_user, json[\"mqtt_user\"]);\r\n          strcpy(mqtt_password, json[\"mqtt_password\"]);\r\n          strcpy(mqtt_pathtemp, json[\"mqtt_pathtemp\"]);\r\n          strcpy(mqtt_pathhum, json[\"mqtt_pathhum\"]);\r\n        } else {\r\n          Serial.println(\"failed to load json config\");\r\n        }\r\n      }\r\n    }\r\n  } else {\r\n    Serial.println(\"failed to mount FS\");\r\n  }\r\n  \/\/end read\r\n\r\n  WiFiManagerParameter custom_mqtt_server(\"server\", \"mqtt server\", mqtt_server, 15);\r\n  WiFiManagerParameter custom_mqtt_user(\"user\", \"mqtt user\", mqtt_user, 20);\r\n  WiFiManagerParameter custom_mqtt_password(\"password\", \"mqtt password\", mqtt_password, 20);\r\n  WiFiManagerParameter custom_mqtt_pathtemp(\"pathtemp\", \"mqtt path temp\", mqtt_pathtemp, 40);\r\n  WiFiManagerParameter custom_mqtt_pathhum(\"pathhum\", \"mqtt path hum\", mqtt_pathhum, 40);\r\n\r\n  \/\/ WiFiManager\r\n  \/\/ Local intialization. Once its business is done, there is no need to keep it around\r\n  WiFiManager wifiManager;\r\n\r\n  \/\/set config save notify callback\r\n  wifiManager.setSaveConfigCallback(saveConfigCallback);\r\n\r\n  \/\/ set custom ip for portal\r\n  \/\/wifiManager.setAPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));\r\n\r\n  \/\/add all your parameters here\r\n  wifiManager.addParameter(&amp;custom_mqtt_server);\r\n  wifiManager.addParameter(&amp;custom_mqtt_user);\r\n  wifiManager.addParameter(&amp;custom_mqtt_password);\r\n  wifiManager.addParameter(&amp;custom_mqtt_pathtemp);\r\n  wifiManager.addParameter(&amp;custom_mqtt_pathhum);\r\n\r\n  \/\/ Uncomment and run it once, if you want to erase all the stored information\r\n  \/\/wifiManager.resetSettings();\r\n\r\n  \/\/set minimum quality of signal so it ignores AP's under that quality\r\n  \/\/defaults to 8%\r\n  \/\/wifiManager.setMinimumSignalQuality();\r\n\r\n  \/\/sets timeout until configuration portal gets turned off\r\n  \/\/useful to make it all retry or go to sleep\r\n  \/\/in seconds\r\n  wifiManager.setTimeout(180);\r\n\r\n  \/\/ fetches ssid and pass from eeprom and tries to connect\r\n  \/\/ if it does not connect it starts an access point with the specified name\r\n  \/\/ here  \"AutoConnectAP\"\r\n  \/\/ and goes into a blocking loop awaiting configuration\r\n  \/\/ wifiManager.autoConnect(\"RustiSensor\");  \/\/ Normale Routine\r\n  \/\/ or use this for auto generated name ESP + ChipID\r\n  \/\/ wifiManager.autoConnect();\r\n\r\n  \/\/ Start WiFi Manager mit Timeout \u00dcberpr\u00fcfung. Nach Timeout... Tiefschlaf\r\n  if (!wifiManager.autoConnect(\"RustiSensor\")) {\r\n    Serial.println(\"failed to connect and hit timeout\");\r\n    delay(3000);\r\n    \/\/reset and try again, or maybe put it to deep sleep\r\n    ESP.deepSleep(0); \/\/ sleep forever\r\n  }\r\n\r\n  \/\/ if you get here you have connected to the WiFi\r\n  Serial.println(\"Connected.\");\r\n\r\n  strcpy(mqtt_server, custom_mqtt_server.getValue());\r\n  strcpy(mqtt_user, custom_mqtt_user.getValue());\r\n  strcpy(mqtt_password, custom_mqtt_password.getValue());\r\n  strcpy(mqtt_pathtemp, custom_mqtt_pathtemp.getValue());\r\n  strcpy(mqtt_pathhum, custom_mqtt_pathhum.getValue());\r\n\r\n  Serial.println(\"saved MQTT params:\");\r\n  Serial.println(mqtt_server);\r\n  Serial.println(mqtt_user);\r\n  Serial.println(mqtt_password);\r\n  Serial.println(mqtt_pathtemp);\r\n  Serial.println(mqtt_pathhum);\r\n\r\n  \/\/save the custom parameters to FS\r\n  if (shouldSaveConfig) {\r\n    Serial.println(\"saving config\");\r\n    DynamicJsonBuffer jsonBuffer;\r\n    JsonObject&amp; json = jsonBuffer.createObject();\r\n    json[\"mqtt_server\"] = mqtt_server;\r\n    json[\"mqtt_user\"] = mqtt_user;\r\n    json[\"mqtt_password\"] = mqtt_password;\r\n    json[\"mqtt_pathtemp\"] = mqtt_pathtemp;\r\n    json[\"mqtt_pathhum\"] = mqtt_pathhum;\r\n\r\n    LittleFS.format(); \/\/ weiss nicht, ob das n\u00f6tig ist, schadet aber nicht.\r\n    File configFile = LittleFS.open(\"\/config.json\", \"w\");\r\n    if (!configFile) {\r\n      Serial.println(\"failed to open config file for writing\");\r\n    }\r\n\r\n    json.printTo(Serial);\r\n    json.printTo(configFile);\r\n    configFile.close();\r\n    \/\/end save\r\n  }\r\n\r\n  WiFi.softAPdisconnect (true); \/\/ turns off Access Point visibility in net neighbourhood\r\n\r\n  \/\/+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n  \/\/++++++++++++++++++++++++Sensor activity &amp; MQTT publishing++++++++++++++++++++\r\n  \/\/+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n\r\n \/\/WiFi.begin(ssid, password); \/\/ not needed! WiFi Manager's job!\r\n WiFi.begin(); \/\/ Unter Umst\u00e4nden erforderlich wenn der D1 Mini nicht connected\r\n \/\/ Nachfolgende WHILE Schleife wird ben\u00f6tigt, um sauber mit dem Router zu connecten. \r\n \/\/ Insbesondere die Fritz!Box hat sonst manchmal Probleme beim Aufwachen aus dem Stromsparmodus. \r\n   while (WiFi.status() != WL_CONNECTED) {\r\n      delay(100); \r\n      Serial.print(\".\");\r\n      WiFiConnRetry++;\r\n      if (WiFiConnRetry &gt;= WiFiConnMax){\r\n         Serial.println(\"No WiFi Connect, sleep 30 mins\");\r\n         delay(1000);\r\n         ESP.deepSleep(1800e6);\r\n       }\r\n   }\r\n\r\n  mqtt.begin(mqtt_server, net);\r\n  mqtt.loop();\r\n  delay(10);\r\n  while (!mqtt.connect(mqtt_server, mqtt_user, mqtt_password)) {\r\n    Serial.print(\"MQTT connect \");\r\n    Serial.println(MQTTReconnects);\r\n    MQTTReconnects++;\r\n    if (MQTTReconnects &gt; MaxReconnects) {\r\n      Serial.println(\"No MQTT Connect, going to sleep\");\r\n      delay(1000);\r\n      ESP.deepSleep(1800e6);  \/\/30 Minuten\r\n    }\r\n    delay(500);\r\n  }\r\n  Serial.println(\"MQTT connection established!\");\r\n\r\n  dht.begin();\r\n  delay(2000);\r\n\r\n  float temp = dht.readTemperature();\r\n  float humidity = dht.readHumidity();\r\n  Serial.print(\"MQTT Status: \");\r\n  Serial.println(mqtt.connected());\r\n  Serial.print(\"Sending... \");\r\n  Serial.println();\r\n  if (!isnan(humidity) || !isnan(temp)) {\r\n    Serial.print(\"Temp: \");\r\n    Serial.print(String(temp));\r\n    Serial.print(\" Humidity: \");\r\n    Serial.println(String(humidity));\r\n    mqtt.publish(String(mqtt_pathtemp), String(temp));\r\n    mqtt.publish(String(mqtt_pathhum), String(humidity));\r\n    mqtt.disconnect();\r\n  }\r\n\r\n  Serial.println(\"Going into deep sleep for xx seconds\");\r\n  ESP.deepSleep(1800e6); \/\/ e.g. 20e6 is 20 seconds\r\n}\r\n\r\nvoid loop() {}<\/pre>\n<p>F\u00fcr viele F\u00e4lle reicht das. Nachteil ist nat\u00fcrlich, dass man nicht so ohne Weiteres\u00a0 an die MQTT Parameter herankommt, wenn man sie einmal gespeichert hat. Entweder geht man mit dem Microcontroller und dessen Stromversorgung nach drau\u00dfen, wo es keinen Empfang gibt oder man schaltet das WLAN kurz ab &#8211; in beiden F\u00e4llen w\u00fcrde dann das so genannte \"Captive Portal\" aufgerufen. Vorteil dieser L\u00f6sung ist, dass man keine zus\u00e4tzliche Hardware verl\u00f6ten muss.<\/p>\n<h4>2b &#8211; Konfiguration mit Button starten<\/h4>\n<p>Elegant w\u00e4re es, wenn man die Konfiguration per Knopfdruck starten k\u00f6nnte &#8211; ganz \u00e4hnlich wie bei den professionellen Sensoren \u00e0 la Shelly. Hierzu liefert der Autor des WiFi Managers ein sch\u00f6nes Beispiel, das ich entsprechend modifiziert habe. Im Original ist die Routine im Loop{} Bereich untergebracht und kann jederzeit mittels Knopfdruck gestartet werden.<\/p>\n<p>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.<\/p>\n<p>Der Button wird an einem freien GPIO Pin des Controllers angeschlossen und zieht beim Dr\u00fccken den Pin auf Low &#8211; also gegen Masse. Ein Fritzing Diagramm daf\u00fcr findet ihr weiter unten.<\/p>\n<p>Ich habe aus bautechnischen Gr\u00fcnden den Pin D4 bzw GPIO 2 verwendet. Die <a href=\"https:\/\/www.rustimation.eu\/index.php\/esp8266-d1-mini-sensor-mit-mqtt\/\">Platine aus dem letzten D1 Mini Beitrag<\/a> habe ich entspreched angepasst und einen Drucktaster\u00a0\u00a0 auf der R\u00fcckseite der Tr\u00e4gerplatine zwischen D4 und GND eingel\u00f6tet.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-1492\" src=\"https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/Photo-2020-12-12-12-35-40_3869-768x1024.jpg\" alt=\"\" width=\"604\" height=\"805\" srcset=\"https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/Photo-2020-12-12-12-35-40_3869-768x1024.jpg 768w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/Photo-2020-12-12-12-35-40_3869-225x300.jpg 225w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/Photo-2020-12-12-12-35-40_3869-1152x1536.jpg 1152w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/Photo-2020-12-12-12-35-40_3869.jpg 1512w\" sizes=\"auto, (max-width: 604px) 100vw, 604px\" \/><\/p>\n<p><em>Abbildung 4: R\u00fcckseite mit eingel\u00f6tetem Button<\/em><\/p>\n<p>Die Stromversorgung erfolgt mittels vier AA Akkus, die nominell 4,8 V liefern und somit an den 5V Anschlusspin gel\u00f6tet werden. Dieser vertr\u00e4gt Spannungen von 3 bis 7V<\/p>\n<h5>Der Sketch<\/h5>\n<pre class=\"height-set:true height:300 lang:c mark:219 decode:true\" title=\"DHT22 Sensor mit Konfigurationsroutine \u00fcber Button aufzurufen\">\/*********\r\n  Credits:\r\n  WiFi Manager Library und allgemeines Vorgehen: https:\/\/github.com\/tzapu\/WiFiManager\r\n  Rui Santos: JSON Routine f\u00fcr Sparameterspeicherung - JSON Library muss &lt; v6 sein!\r\n              project details at http:\/\/randomnerdtutorials.com\r\n  Mit LittleFS realisiert anstatt SPIFFS\r\n \r\n  Nach dem Starten oder einem Reset hat der User ca. 3 Sekunden Zeit, den Config-\r\n  Button zu dr\u00fccken. Der Controller geht dann in den Setup Modus. \r\n  Achtung: Es muss in jedem Fall ein Wifi Passwort (PSK) eingegeben werden, damit\r\n           ge\u00e4nderte Daten gespeichert werden. \r\n \r\n*********\/\r\n \r\n#include &lt;LittleFS.h&gt; \/\/this needs to be first, or it all crashes and burns...\r\n#include &lt;ESP8266WiFi.h&gt;\r\n#include &lt;DNSServer.h&gt;\r\n#include &lt;ESP8266WebServer.h&gt;\r\n#include &lt;WiFiManager.h&gt;          \/\/ https:\/\/github.com\/tzapu\/WiFiManager\r\n#include &lt;ArduinoJson.h&gt;          \/\/ https:\/\/github.com\/bblanchon\/ArduinoJson\r\n \r\n#include \"DHT_U.h\"\r\n#include &lt;MQTT.h&gt;\r\n \r\n#define DHTTYPE DHT22\r\n#define DHTPIN 14\r\n \r\n\/\/ select which pin will trigger the configuration portal when set to LOW\r\n#define TRIGGER_PIN 2\r\n \r\n\/\/ Set web server port number to 80\r\nWiFiServer server(80);\r\nWiFiClient net;\r\nMQTTClient mqtt;\r\n \r\nDHT dht(DHTPIN, DHTTYPE);\r\nchar mqtt_server[15] = \"IP Adresse\";\r\nchar mqtt_user[20] = \"MQTT User\";\r\nchar mqtt_password[20] = \"MQTT Password\";\r\nchar mqtt_pathtemp[40] = \"\/Pfad\/Temperatur\";\r\nchar mqtt_pathhum[40] = \"\/Pfad\/Luftfeuchtigkeit\";\r\n \r\nint MaxReconnects = 5; \/\/ Max Anzahl MQTT Server Verbindungsversuche\r\nint MQTTReconnects = 0; \/\/ Z\u00e4hler f\u00fcr MQTT Reconnects\r\nint WiFiConnRetry=0; \/\/ Z\u00e4hler f\u00fcr WiFi Connect Retrys\r\nint WiFiConnMax=100; \/\/ Max Anzahl WiFi Verbindungsversuche\r\n \r\nint loopctr = 0;    \/\/Z\u00e4hler Schleifendurchl\u00e4ufe - Warten auf Triggger\r\nbool keypressed = false;\r\n\/\/flag for saving data\r\nbool shouldSaveConfig = false;\r\n \r\n\/\/callback notifying us of the need to save config\r\nvoid saveConfigCallback () {\r\n  Serial.println(\"Should save config\");\r\n  shouldSaveConfig = true;\r\n}\r\n \r\nvoid setup() {\r\n  Serial.begin(115200);\r\n  Serial.println();\r\n  Serial.println(\"Booting...\");\r\n \r\n  \/\/Blinker\r\n  pinMode(LED_BUILTIN, OUTPUT);\r\n  digitalWrite(LED_BUILTIN, HIGH);\r\n \r\n  \/\/clean FS, for testing\r\n  \/\/LittleFS.format();\r\n \r\n  \/\/read configuration from FS json\r\n  Serial.println(\"mounting FS...\");\r\n \r\n  if (LittleFS.begin()) {\r\n    Serial.println(\"mounted file system\");\r\n    if (LittleFS.exists(\"\/config.json\")) {\r\n      \/\/file exists, reading and loading\r\n      Serial.println(\"reading config file\");\r\n      File configFile = LittleFS.open(\"\/config.json\", \"r\");\r\n      if (configFile) {\r\n        Serial.println(\"opened config file\");\r\n        size_t size = configFile.size();\r\n        \/\/ Allocate a buffer to store contents of the file.\r\n        std::unique_ptr&lt;char[]&gt; buf(new char[size]);\r\n \r\n        configFile.readBytes(buf.get(), size);\r\n        DynamicJsonBuffer jsonBuffer;\r\n        JsonObject&amp; json = jsonBuffer.parseObject(buf.get());\r\n        json.printTo(Serial);\r\n        if (json.success()) {\r\n          Serial.println(\"\\nparsed json\");\r\n          strcpy(mqtt_server, json[\"mqtt_server\"]);\r\n          strcpy(mqtt_user, json[\"mqtt_user\"]);\r\n          strcpy(mqtt_password, json[\"mqtt_password\"]);\r\n          strcpy(mqtt_pathtemp, json[\"mqtt_pathtemp\"]);\r\n          strcpy(mqtt_pathhum, json[\"mqtt_pathhum\"]);\r\n        } else {\r\n          Serial.println(\"failed to load json config\");\r\n        }\r\n      }\r\n    }\r\n  } else {\r\n    Serial.println(\"failed to mount FS\");\r\n  }\r\n  \/\/end read\r\n \r\n  WiFiManagerParameter custom_mqtt_server(\"server\", \"mqtt server\", mqtt_server, 15);\r\n  WiFiManagerParameter custom_mqtt_user(\"user\", \"mqtt user\", mqtt_user, 20);\r\n  WiFiManagerParameter custom_mqtt_password(\"password\", \"mqtt password\", mqtt_password, 20);\r\n  WiFiManagerParameter custom_mqtt_pathtemp(\"pathtemp\", \"mqtt path temp\", mqtt_pathtemp, 40);\r\n  WiFiManagerParameter custom_mqtt_pathhum(\"pathhum\", \"mqtt path hum\", mqtt_pathhum, 40);\r\n \r\n  \/\/Schleife zum Erkennen, ob Trigger aktiv\r\n \r\n  while (!keypressed &amp;&amp; loopctr &lt; 3)\r\n  {\r\n    if ( digitalRead(TRIGGER_PIN) == LOW ) {\r\n      keypressed = true;\r\n      Serial.println(\"Key pressed!!\");\r\n    }\r\n    delay(1000);\r\n    \/\/Serial.println(loopctr);\r\n    loopctr++;\r\n  }\r\n \r\n  \/\/ WiFiManager nur, wenn Trigger vorher aktiviert wurde\r\n  if (keypressed) {\r\n    blink(100, 200, 5);\r\n    \/\/ Local intialization. Once its business is done, there is no need to keep it around\r\n    WiFiManager wifiManager;\r\n \r\n    \/\/set config save notify callback\r\n    wifiManager.setSaveConfigCallback(saveConfigCallback);\r\n \r\n    \/\/add all your parameters here\r\n    wifiManager.addParameter(&amp;custom_mqtt_server);\r\n    wifiManager.addParameter(&amp;custom_mqtt_user);\r\n    wifiManager.addParameter(&amp;custom_mqtt_password);\r\n    wifiManager.addParameter(&amp;custom_mqtt_pathtemp);\r\n    wifiManager.addParameter(&amp;custom_mqtt_pathhum);\r\n \r\n    \/\/ erase all the stored information\r\n    wifiManager.resetSettings();\r\n \r\n    \/\/set minimum quality of signal so it ignores AP's under that quality\r\n    \/\/defaults to 8%\r\n    \/\/wifiManager.setMinimumSignalQuality();\r\n \r\n    \/\/sets timeout until configuration portal gets turned off\r\n    \/\/useful to make it all retry or go to sleep\r\n    \/\/in seconds\r\n    wifiManager.setTimeout(180);\r\n \r\n    \/\/ fetches ssid and pass from eeprom and tries to connect\r\n    \/\/ if it does not connect it starts an access point with the specified name\r\n    \/\/ here  \"AutoConnectAP\"\r\n    \/\/ and goes into a blocking loop awaiting configuration\r\n    \/\/ wifiManager.autoConnect(\"RustiSensor\");  \/\/ Normale Routine\r\n    \/\/ or use this for auto generated name ESP + ChipID\r\n    \/\/ wifiManager.autoConnect();\r\n \r\n    \/\/ Start WiFi Manager mit Timeout \u00dcberpr\u00fcfung. Nach Timeout... Tiefschlaf\r\n    if (!wifiManager.startConfigPortal(\"RustiSensor\")) {\r\n      Serial.println(\"failed to connect and hit timeout\");\r\n      delay(3000);\r\n      \/\/reset and try again, or maybe put it to deep sleep\r\n      ESP.deepSleep(0); \/\/ sleep forever\r\n    }\r\n \r\n    \/\/ if you get here you have connected to the WiFi\r\n    Serial.println(\"Connected.\");\r\n \r\n    strcpy(mqtt_server, custom_mqtt_server.getValue());\r\n    strcpy(mqtt_user, custom_mqtt_user.getValue());\r\n    strcpy(mqtt_password, custom_mqtt_password.getValue());\r\n    strcpy(mqtt_pathtemp, custom_mqtt_pathtemp.getValue());\r\n    strcpy(mqtt_pathhum, custom_mqtt_pathhum.getValue());\r\n \r\n    Serial.println(\"saved MQTT params:\");\r\n    Serial.println(mqtt_server);\r\n    Serial.println(mqtt_user);\r\n    Serial.println(mqtt_password);\r\n    Serial.println(mqtt_pathtemp);\r\n    Serial.println(mqtt_pathhum);\r\n \r\n    Serial.print(\"Should save----&gt;\");\r\n    Serial.println(shouldSaveConfig);\r\n \r\n    \/\/save the custom parameters to FS\r\n    if (shouldSaveConfig) {\r\n      Serial.println(\"saving config\");\r\n      DynamicJsonBuffer jsonBuffer;\r\n      JsonObject&amp; json = jsonBuffer.createObject();\r\n      json[\"mqtt_server\"] = mqtt_server;\r\n      json[\"mqtt_user\"] = mqtt_user;\r\n      json[\"mqtt_password\"] = mqtt_password;\r\n      json[\"mqtt_pathtemp\"] = mqtt_pathtemp;\r\n      json[\"mqtt_pathhum\"] = mqtt_pathhum;\r\n \r\n      LittleFS.format(); \/\/ weiss nicht, ob das n\u00f6tig ist, schadet aber nicht.\r\n      File configFile = LittleFS.open(\"\/config.json\", \"w\");\r\n      if (!configFile) {\r\n        Serial.println(\"failed to open config file for writing\");\r\n      }\r\n \r\n      json.printTo(Serial);\r\n      json.printTo(configFile);\r\n      configFile.close();\r\n      \/\/end save\r\n    }\r\n  }\r\n \r\n  WiFi.softAPdisconnect (true); \/\/ turns off Access Point visibility in net neighbourhood\r\n \r\n  \/\/+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n  \/\/++++++++++++++++++++++++Sensor activity &amp; MQTT publishing++++++++++++++++++++\r\n  \/\/+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n \/\/WiFi.begin(ssid, password); \/\/ not needed! WiFi Manager's job!\r\nWiFi.begin(); \/\/ bei neueren Versionen der Libraries erforderlich wenn D1 Mini nicht connecten will\r\n \/\/ Nachfolgende WHILE Schleife wird ben\u00f6tigt, um sauber mit dem Router zu connecten. \r\n \/\/ Insbesondere die Fritz!Box hat manchmal Probleme beim Aufwachen aus dem Stromsparmodus. \r\nwhile (WiFi.status() != WL_CONNECTED) {\r\n   delay(100); \r\n   Serial.print(\".\");\r\n   WiFiConnRetry++;\r\n   if (WiFiConnRetry &gt;= WiFiConnMax){\r\n      Serial.println(\"No WiFi Connect, sleep 30 mins\");\r\n      delay(1000);\r\n      ESP.deepSleep(1800e6);\r\n    }\r\n}\r\n  mqtt.begin(mqtt_server, net);\r\n  mqtt.loop();\r\n  delay(10);\r\n  while (!mqtt.connect(mqtt_server, mqtt_user, mqtt_password)) {\r\n    Serial.print(\"MQTT connect \");\r\n    Serial.println(MQTTReconnects);\r\n    ++MQTTReconnects;\r\n    if (MQTTReconnects &gt; MaxReconnects) {\r\n      blink(250, 200, 3); \/\/\"S\"\r\n      delay(1500);\r\n      blink(1000, 200, 3); \/\/\"O\"\r\n      delay(1500);\r\n      blink(250, 200, 3); \/\/\"S\"\r\n      Serial.println(\"No MQTT Connect, going to sleep\");\r\n      delay(1000);\r\n      ESP.deepSleep(1800e6);\r\n    }\r\n    delay(500);\r\n  }\r\n  Serial.println(\"MQTT connection established!\");\r\n \r\n  dht.begin();\r\n  delay(2000);\r\n \r\n  float temp = dht.readTemperature();\r\n  float humidity = dht.readHumidity();\r\n  Serial.print(\"MQTT Status: \");\r\n  Serial.println(mqtt.connected());\r\n  Serial.print(\"Sending... \");\r\n  Serial.println();\r\n  if (!isnan(humidity) || !isnan(temp)) {\r\n    Serial.print(\"Temp: \");\r\n    Serial.print(String(temp));\r\n    Serial.print(\" Humidity: \");\r\n    Serial.println(String(humidity));\r\n    mqtt.publish(String(mqtt_pathtemp), String(temp));\r\n    mqtt.publish(String(mqtt_pathhum), String(humidity));\r\n    mqtt.disconnect();\r\n  }\r\n \r\n  Serial.println(\"Going into deep sleep for xx seconds\");\r\n  ESP.deepSleep(1885e6); \/\/ e.g. 20e6 is 20 seconds\r\n}\r\n \r\nvoid loop() {}\r\n \r\nvoid blink(int t1, int t0, int n) {\r\n  \/\/ Schaltet LED ein und aus. \u00dcbergabeparameter: Millisekunden Ein,\r\n  \/\/ Millisekunden aus, Anzahl Blinks\r\n  \/\/ Optional - ggf. weglassen, um Strom zu sparen\r\n  int b = 0;\r\n  while (b &lt;= n) {\r\n    digitalWrite(LED_BUILTIN, LOW);\r\n    delay(t1);\r\n    digitalWrite(LED_BUILTIN, HIGH);\r\n    delay(t0);\r\n    b++;\r\n  }\r\n}<\/pre>\n<p>Funktioniert schon ganz gut. Ein Nachteil ist allerdings, dass die ge\u00e4nderten Daten nur dann gespeichert werden, wenn man auch die SSID und das WLAN Passwort (PSK) wieder eintr\u00e4gt.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-1470\" src=\"https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/IMG_3835-1024x768.jpg\" alt=\"\" width=\"604\" height=\"453\" srcset=\"https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/IMG_3835-1024x768.jpg 1024w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/IMG_3835-300x225.jpg 300w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/IMG_3835-768x576.jpg 768w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/IMG_3835-1536x1152.jpg 1536w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/IMG_3835.jpg 2016w\" sizes=\"auto, (max-width: 604px) 100vw, 604px\" \/><\/p>\n<p><em>Abbildung 5: Versuchsaufbau auf Breadboard<\/em><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-1497\" src=\"https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/Image1-1024x854.jpg\" alt=\"\" width=\"604\" height=\"504\" srcset=\"https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/Image1-1024x854.jpg 1024w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/Image1-300x250.jpg 300w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/Image1-768x641.jpg 768w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/12\/Image1.jpg 1033w\" sizes=\"auto, (max-width: 604px) 100vw, 604px\" \/><\/p>\n<p><em>Abbidung 6: Fritzing Diagramm (Reset Verbindung zwischen D0 und RST &#8211; gr\u00fcn &#8211; Jumper)<\/em><\/p>\n<p>Wenn ihr tiefer einsteigen wollt, kann ich euch das Kapitel \u00fcber den D1 Mini in <a href=\"https:\/\/wolles-elektronikkiste.de\/wemos-d1-mini-boards\" target=\"_blank\" rel=\"noopener\">Wolles Elektronikkiste<\/a> nur w\u00e4rmstens empfehlen!<\/p>\n<p>Wie immer: Fragen oder Kritik sind erw\u00fcnscht &#8211; Kommentarfunktion.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>WiFi Credentials immmer wieder neu zu programmieren ist l\u00e4stig. Hier zeige ich verschiedene Methoden, wie ein ESP8266 basierender Controller ohne Neu-Programmieren mit SSID, Passwort und ggf. MQTT Parametern versehen werden kann.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[103,112,102,3,53,4],"tags":[101,110,109,77,115,111,76],"class_list":["post-1455","post","type-post","status-publish","format-standard","hentry","category-arduino","category-d1-mini","category-esp8266-esp32","category-fernsteuern","category-iot","category-json","tag-dht22","tag-psk","tag-ssid","tag-wifi","tag-wifi-credentials","tag-wifimanager","tag-wlan"],"_links":{"self":[{"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/posts\/1455","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/comments?post=1455"}],"version-history":[{"count":1,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/posts\/1455\/revisions"}],"predecessor-version":[{"id":2871,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/posts\/1455\/revisions\/2871"}],"wp:attachment":[{"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/media?parent=1455"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/categories?post=1455"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/tags?post=1455"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}