diff --git a/M5Atom_airqa.ino b/M5Atom_airqa.ino new file mode 100644 index 0000000..4da8078 --- /dev/null +++ b/M5Atom_airqa.ino @@ -0,0 +1,227 @@ +#include // https://github.com/tzapu/WiFiManager +#include //Сохранение настроек хеша прошивки + +#include +#include + +//Наша кнопочка при нажатии на которую произойдет вызов wifi менеджера и перезагрузка в станцию +#define TRIGGER_PIN 39 + +WiFiManager wm; // обьект менеджера +WiFiManagerParameter custom_field; +Preferences OTApreferences; + +unsigned long timingUpdate; +int PROGMEM nextM5Update = 450000; //каждые 7.5 минут запрос обновления с сервера + +void setup() +{ + WiFi.mode(WIFI_STA); + Serial.begin(115200); + Serial.setDebugOutput(true); + delay(3000); + Serial.println("\n Starting station"); + pinMode(TRIGGER_PIN, INPUT); + // wm.resetSettings(); // wipe settings + // add a custom input field + int customFieldLength = 40; + // new (&custom_field) WiFiManagerParameter("customfieldid", "Custom Field Label", "Custom Field Value", customFieldLength,"placeholder=\"Custom Field Placeholder\""); + // test custom html input type(checkbox) + // new (&custom_field) WiFiManagerParameter("customfieldid", "Custom Field Label", "Custom Field Value", customFieldLength,"placeholder=\"Custom Field Placeholder\" type=\"checkbox\""); // custom html type + // test custom html(radio) + const char *custom_radio_str = "
One
Two
Three"; + new (&custom_field) WiFiManagerParameter(custom_radio_str); // custom html input + wm.addParameter(&custom_field); + wm.setSaveParamsCallback(saveParamCallback); + // custom menu via array or vector + // menu tokens, "wifi","wifinoscan","info","param","close","sep","erase","restart","exit" (sep is seperator) (if param is in menu, params will not show up in wifi page!) + // const char* menu[] = {"wifi","info","param","sep","restart","exit"}; + // wm.setMenu(menu,6); + std::vector menu = {"wifi", "info", "param", "sep", "restart", "exit"}; + wm.setMenu(menu); + // set dark theme + wm.setClass("invert"); + //set static ip + // wm.setSTAStaticIPConfig(IPAddress(10,0,1,99), IPAddress(10,0,1,1), IPAddress(255,255,255,0)); // set static ip,gw,sn + // wm.setShowStaticFields(true); // force show static ip fields + // wm.setShowDnsFields(true); // force show dns field always + // wm.setConnectTimeout(20); // how long to try to connect for before continuing + wm.setConfigPortalTimeout(30); // auto close configportal after n seconds + // wm.setCaptivePortalEnable(false); // disable captive portal redirection + // wm.setAPClientCheck(true); // avoid timeout if client connected to softap + // wifi scan settings + // wm.setRemoveDuplicateAPs(false); // do not remove duplicate ap names (true) + // wm.setMinimumSignalQuality(20); // set min RSSI (percentage) to show in scans, null = 8% + // wm.setShowInfoErase(false); // do not show erase button on info page + // wm.setScanDispPerc(true); // show RSSI as percentage not graph icons + // wm.setBreakAfterConfig(true); // always exit configportal even if wifi save fails + bool res; + // res = wm.autoConnect(); // auto generated AP name from chipid + // res = wm.autoConnect("AutoConnectAP"); // anonymous ap + res = wm.autoConnect("AutoConnectAP", "password"); // password protected ap + if (!res) + { + Serial.println("Failed to connect or hit timeout"); + // ESP.restart(); + } + else + { + //if you get here you have connected to the WiFi + Serial.println("connected..."); + } +} + +void checkButton() +{ + if (digitalRead(TRIGGER_PIN) == LOW) + { + delay(50); + if (digitalRead(TRIGGER_PIN) == LOW) + { + Serial.println("Button Pressed"); + delay(3000); + if (digitalRead(TRIGGER_PIN) == LOW) + { + Serial.println("Button Held"); + Serial.println("Erasing Config, restarting"); + wm.resetSettings(); + ESP.restart(); + } + + // start portal w delay + Serial.println("Starting config portal"); + wm.setConfigPortalTimeout(120); + + if (!wm.startConfigPortal("AirQaPOrtal", "12345678")) + { + Serial.println("failed to connect or hit timeout"); + delay(3000); + // ESP.restart(); + } + else + { + Serial.println("connected.."); + } + } + } +} + +String getParam(String name) +{ + String value; + if (wm.server->hasArg(name)) + { + value = wm.server->arg(name); + } + return value; +} + +void saveParamCallback() +{ + Serial.println("[CALLBACK] saveParamCallback fired"); + Serial.println("PARAM customfieldid = " + getParam("customfieldid")); +} + +void OTAUpdate() +{ + + Serial.println("OTAUpdate()"); + //http://meteosence.s-host.net/meteosence.php?meteopas=PdF4apD4i95xR5&meteodata=gethash + + bool flagOTA = false; + String keyOTA; + String payload; + + OTApreferences.begin("ota-config"); + + if (WiFi.status() == WL_CONNECTED) + { + HTTPClient http; + String serverPath = "http://meteosence.s-host.net/airqa/airquality.php?meteopas=e93gme9hAt9nSWaV&meteodata=gethash"; + http.begin(serverPath.c_str()); + int httpResponseCode = http.GET(); + + if (httpResponseCode > 0) + { + Serial.print("HTTP Response code: "); + Serial.println(httpResponseCode); + payload = http.getString(); + Serial.println(payload); + + keyOTA = OTApreferences.getString("md5HashOTA"); + + if (keyOTA.length() <= 0) + { + OTApreferences.putString("md5HashOTA", "asshole"); + } + + keyOTA = OTApreferences.getString("md5HashOTA"); + + if (payload != keyOTA) + { + flagOTA = true; + OTApreferences.putString("md5HashOTA", payload); + Serial.println("flagOTA = true;"); + } + } + else + { + Serial.print("Error code: "); + Serial.println(httpResponseCode); + } + // Free resources + http.end(); + } + else + { + Serial.println("WiFi Disconnected"); + } + + if (flagOTA == true) + { + flagOTA = false; + Serial.println("flagOTA = false;"); + + t_httpUpdate_return ret = ESPhttpUpdate.update("http://meteosence.s-host.net/airqa/airatoms.bin"); + + Serial.print("ret "); + Serial.println(ret); + + switch (ret) + { + case HTTP_UPDATE_FAILED: + Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str()); + Serial.println(ESPhttpUpdate.getLastError()); + Serial.println(ESPhttpUpdate.getLastErrorString().c_str()); + Serial.println("HTTP_UPDATE_FAILD Error"); + delay(3000); + ESP.restart(); + break; + + case HTTP_UPDATE_NO_UPDATES: + Serial.println("HTTP_UPDATE_NO_UPDATES"); + delay(3000); + ESP.restart(); + break; + + case HTTP_UPDATE_OK: + Serial.println("HTTP_UPDATE_OK"); + delay(3000); + ESP.restart(); + break; + } + } + OTApreferences.end(); +} + +void loop() +{ + //Проверка старта сервера + checkButton(); + //По таймеру запруск обновления - проверка хеша прошивки на сервере + if (millis() - timingUpdate > nextM5Update) + { + OTAUpdate(); + timingUpdate = millis(); + } +} \ No newline at end of file