/************************************************************** * This is a DEMO. You can use it only for development and testing. * * If you would like to add these features to your product, * please contact Blynk for Business: * * http://www.blynk.io/ * **************************************************************/ #include #include #include WebServer server(WIFI_AP_CONFIG_PORT); DNSServer dnsServer; const byte DNS_PORT = 53; const char* config_form = R"html( WiFi setup

)html"; void restartMCU() { ESP.restart(); } void enterConfigMode() { randomSeed(ESP.getEfuseMac() & 0xFFFFFF); const uint32_t unique = random(0xFFFFF); char ssidBuff[64]; snprintf(ssidBuff, sizeof(ssidBuff), "%s-%05X", PRODUCT_WIFI_SSID, unique); WiFi.mode(WIFI_OFF); delay(100); WiFi.mode(WIFI_AP); WiFi.softAPConfig(WIFI_AP_IP, WIFI_AP_IP, WIFI_AP_Subnet); WiFi.softAP(ssidBuff); delay(500); IPAddress myIP = WiFi.softAPIP(); DEBUG_PRINT(String("AP SSID: ") + ssidBuff); DEBUG_PRINT(String("AP IP: ") + myIP[0] + "." + myIP[1] + "." + myIP[2] + "." + myIP[3]); // Set up DNS Server dnsServer.setTTL(300); // Time-to-live 300s dnsServer.setErrorReplyCode(DNSReplyCode::ServerFailure); // Return code for non-accessible domains #ifdef WIFI_CAPTIVE_PORTAL_ENABLE dnsServer.start(DNS_PORT, "*", WiFi.softAPIP()); // Point all to our IP server.onNotFound(handleRoot); #else dnsServer.start(DNS_PORT, BOARD_CONFIG_AP_URL, WiFi.softAPIP()); DEBUG_PRINT(String("AP URL: ") + BOARD_CONFIG_AP_URL); #endif server.on("/", []() { server.send(200, "text/html", config_form); }); server.on("/config", []() { String ssid = server.arg("ssid"); String ssidManual = server.arg("ssidManual"); String pass = server.arg("pass"); if (ssidManual != "") { ssid = ssidManual; } String token = server.arg("blynk"); String host = server.arg("host"); String port = server.arg("port"); String content; unsigned statusCode; DEBUG_PRINT(String("WiFi SSID: ") + ssid + " Pass: " + pass); DEBUG_PRINT(String("Blynk cloud: ") + token + " @ " + host + ":" + port); if (token.length() == 32 && ssid.length() > 0) { configStore.flagConfig = false; CopyString(ssid, configStore.wifiSSID); CopyString(pass, configStore.wifiPass); CopyString(token, configStore.cloudToken); if (host.length()) { CopyString(host, configStore.cloudHost); } if (port.length()) { configStore.cloudPort = port.toInt(); } content = R"json({"status":"ok","msg":"Configuration saved"})json"; statusCode = 200; server.send(statusCode, "application/json", content); BlynkState::set(MODE_SWITCH_TO_STA); } else { DEBUG_PRINT("Configuration invalid"); content = R"json({"status":"error","msg":"Configuration invalid"})json"; statusCode = 404; server.send(statusCode, "application/json", content); } }); server.on("/board_info.json", []() { char buff[256]; snprintf(buff, sizeof(buff), R"json({"board":"%s","vendor":"%s","tmpl_id":"%s","fw_ver":"%s","hw_ver":"%s"})json", BOARD_NAME, BOARD_VENDOR, BOARD_TEMPLATE_ID, BOARD_FIRMWARE_VERSION, BOARD_HARDWARE_VERSION ); server.send(200, "application/json", buff); }); server.on("/reset", []() { BlynkState::set(MODE_RESET_CONFIG); server.send(200, "application/json", R"json({"status":"ok","msg":"Configuration reset"})json"); }); server.on("/reboot", []() { restartMCU(); }); server.begin(); while (BlynkState::is(MODE_WAIT_CONFIG) || BlynkState::is(MODE_CONFIGURING)) { dnsServer.processNextRequest(); server.handleClient(); if (BlynkState::is(MODE_WAIT_CONFIG) && WiFi.softAPgetStationNum() > 0) { BlynkState::set(MODE_CONFIGURING); } else if (BlynkState::is(MODE_CONFIGURING) && WiFi.softAPgetStationNum() == 0) { BlynkState::set(MODE_WAIT_CONFIG); } } server.stop(); } void enterConnectNet() { BlynkState::set(MODE_CONNECTING_NET); DEBUG_PRINT(String("Connecting to WiFi: ") + configStore.wifiSSID); WiFi.begin(configStore.wifiSSID, configStore.wifiPass); unsigned long timeoutMs = millis() + WIFI_NET_CONNECT_TIMEOUT; while ((timeoutMs > millis()) && (WiFi.status() != WL_CONNECTED)) { delay(100); if (!BlynkState::is(MODE_CONNECTING_NET)) { WiFi.disconnect(); return; } } if (WiFi.status() == WL_CONNECTED) { BlynkState::set(MODE_CONNECTING_CLOUD); } else { BlynkState::set(MODE_ERROR); } } void enterConnectCloud() { BlynkState::set(MODE_CONNECTING_CLOUD); Blynk.disconnect(); Blynk.config(configStore.cloudToken, configStore.cloudHost, configStore.cloudPort); Blynk.connect(0); unsigned long timeoutMs = millis() + WIFI_CLOUD_CONNECT_TIMEOUT; while ((timeoutMs > millis()) && (Blynk.connected() == false)) { Blynk.run(); if (!BlynkState::is(MODE_CONNECTING_CLOUD)) { Blynk.disconnect(); return; } } if (Blynk.connected()) { BlynkState::set(MODE_RUNNING); if (!configStore.flagConfig) { configStore.flagConfig = true; config_save(); DEBUG_PRINT("Configuration stored to flash"); } } else { BlynkState::set(MODE_ERROR); } } void enterSwitchToSTA() { BlynkState::set(MODE_SWITCH_TO_STA); DEBUG_PRINT("Switching to STA..."); WiFi.mode(WIFI_OFF); delay(1000); WiFi.mode(WIFI_STA); BlynkState::set(MODE_CONNECTING_NET); } void enterError() { BlynkState::set(MODE_ERROR); unsigned long timeoutMs = millis() + 10000; while (timeoutMs > millis() || g_buttonPressed) { delay(10); if (!BlynkState::is(MODE_ERROR)) { return; } } DEBUG_PRINT("Restarting after error."); delay(10); restartMCU(); }