diff --git a/src/CHANGES.md b/src/CHANGES.md index ab0963d7..34f9aacc 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,7 @@ ## 0.8.45 - 2024-01-05 * fix MqTT total values #1326 +* start implementing a wizard for initial (WiFi) configuration #1199 ## 0.8.44 - 2024-01-05 * fix MqTT transmission of data #1326 diff --git a/src/app.h b/src/app.h index 8d6fafbe..41ff008b 100644 --- a/src/app.h +++ b/src/app.h @@ -150,6 +150,18 @@ class app : public IApp, public ah::Scheduler { return mWifi.getAvailNetworks(obj); } + void setupStation(void) { + mWifi.setupStation(); + } + + void setStopApAllowedMode(bool allowed) { + mWifi.setStopApAllowedMode(allowed); + } + + String getStationIp(void) { + return mWifi.getStationIp(); + } + #endif /* !defined(ETHERNET) */ void setRebootFlag() { diff --git a/src/appInterface.h b/src/appInterface.h index 9d633765..76c5e935 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -37,6 +37,9 @@ class IApp { #if !defined(ETHERNET) virtual void scanAvailNetworks() = 0; virtual bool getAvailNetworks(JsonObject obj) = 0; + virtual void setupStation(void) = 0; + virtual void setStopApAllowedMode(bool allowed) = 0; + virtual String getStationIp(void) = 0; #endif /* defined(ETHERNET) */ virtual uint32_t getUptime() = 0; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 2b341441..cea845a2 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -100,6 +100,7 @@ class RestApi { else if(path == "setup") getSetup(request, root); #if !defined(ETHERNET) else if(path == "setup/networks") getNetworks(root); + else if(path == "setup/getip") getWifiIp(root); #endif /* !defined(ETHERNET) */ else if(path == "live") getLive(request,root); else { @@ -754,6 +755,9 @@ class RestApi { void getNetworks(JsonObject obj) { mApp->getAvailNetworks(obj); } + void getWifiIp(JsonObject obj) { + obj[F("ip")] = mApp->getStationIp(); + } #endif /* !defined(ETHERNET) */ void getLive(AsyncWebServerRequest *request, JsonObject obj) { @@ -834,7 +838,13 @@ class RestApi { mTimezoneOffset = jsonIn[F("val")]; else if(F("discovery_cfg") == jsonIn[F("cmd")]) mApp->setMqttDiscoveryFlag(); // for homeassistant - else if(F("save_iv") == jsonIn[F("cmd")]) { + else if(F("save_wifi") == jsonIn[F("cmd")]) { + snprintf(mConfig->sys.stationSsid, SSID_LEN, "%s", jsonIn[F("ssid")].as()); + snprintf(mConfig->sys.stationPwd, PWD_LEN, "%s", jsonIn[F("pwd")].as()); + mApp->saveSettings(false); // without reboot + mApp->setStopApAllowedMode(false); + mApp->setupStation(); + } else if(F("save_iv") == jsonIn[F("cmd")]) { Inverter<> *iv = mSys->getInverterByPos(jsonIn[F("id")], false); iv->config->enabled = jsonIn[F("en")]; iv->config->serial.u64 = jsonIn[F("ser")]; diff --git a/src/web/html/style.css b/src/web/html/style.css index e7de68f4..c9f9fbf7 100644 --- a/src/web/html/style.css +++ b/src/web/html/style.css @@ -814,3 +814,20 @@ ul { background-color: var(--input-bg); color: var(--fg); } + +.d-flex { + display: flex !important; +} + +.jc { + justify-content: center !important; +} + +.aic { + align-items: center !important; +} + +.container { + height: 100%; + overflow: auto; +} diff --git a/src/web/html/wizard.html b/src/web/html/wizard.html new file mode 100644 index 00000000..1ebfb65f --- /dev/null +++ b/src/web/html/wizard.html @@ -0,0 +1,87 @@ + + + + Setup Wizard + {#HTML_HEADER} + + +
+
+
+
+
+ + + diff --git a/src/web/web.h b/src/web/web.h index ea25e5ff..eae106a9 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -36,6 +36,7 @@ #include "html/h/update_html.h" #include "html/h/visualization_html.h" #include "html/h/about_html.h" +#include "html/h/wizard_html.h" #define WEB_SERIAL_BUF_SIZE 2048 @@ -77,6 +78,7 @@ class Web { mWeb.on("/factorytrue", HTTP_ANY, std::bind(&Web::showHtml, this, std::placeholders::_1)); mWeb.on("/setup", HTTP_GET, std::bind(&Web::onSetup, this, std::placeholders::_1)); + mWeb.on("/wizard", HTTP_GET, std::bind(&Web::onWizard, this, std::placeholders::_1)); mWeb.on("/save", HTTP_POST, std::bind(&Web::showSave, this, std::placeholders::_1)); mWeb.on("/live", HTTP_ANY, std::bind(&Web::onLive, this, std::placeholders::_1)); @@ -422,7 +424,7 @@ class Web { void showNotFound(AsyncWebServerRequest *request) { checkProtection(request); - request->redirect("/setup"); + request->redirect("/wizard"); } void onReboot(AsyncWebServerRequest *request) { @@ -444,6 +446,13 @@ class Web { getPage(request, PROT_MASK_SETUP, setup_html, setup_html_len); } + void onWizard(AsyncWebServerRequest *request) { + AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), wizard_html, wizard_html_len); + response->addHeader(F("Content-Encoding"), "gzip"); + response->addHeader(F("content-type"), "text/html; charset=UTF-8"); + request->send(response); + } + void showSave(AsyncWebServerRequest *request) { DPRINTLN(DBG_VERBOSE, F("showSave")); diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 02f8d252..4ab7ee92 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -40,6 +40,7 @@ void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb) { mCnt = 0; mScanActive = false; mScanCnt = 0; + mStopApAllowed = true; #if defined(ESP8266) wifiConnectHandler = WiFi.onStationModeConnected(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1)); @@ -94,7 +95,7 @@ void ahoywifi::tickWifiLoop() { #endif return; case IN_AP_MODE: - if (WiFi.softAPgetStationNum() == 0) { + if ((WiFi.softAPgetStationNum() == 0) || (!mStopApAllowed)) { mCnt = 0; mDns.stop(); WiFi.mode(WIFI_AP_STA); @@ -105,7 +106,7 @@ void ahoywifi::tickWifiLoop() { } break; case DISCONNECTED: - if (WiFi.softAPgetStationNum() > 0) { + if ((WiFi.softAPgetStationNum() > 0) && (mStopApAllowed)) { mStaConn = IN_AP_MODE; // first time switch to AP Mode if (mScanActive) { @@ -182,10 +183,12 @@ void ahoywifi::tickWifiLoop() { break; case GOT_IP: welcome(WiFi.localIP().toString(), F(" (Station)")); - WiFi.softAPdisconnect(); - WiFi.mode(WIFI_STA); - DBGPRINTLN(F("[WiFi] AP disabled")); - delay(100); + if(mStopApAllowed) { + WiFi.softAPdisconnect(); + WiFi.mode(WIFI_STA); + DBGPRINTLN(F("[WiFi] AP disabled")); + delay(100); + } mAppWifiCb(true); mGotDisconnect = false; mStaConn = IN_STA_MODE; diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index e44d6858..36837600 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -28,6 +28,13 @@ class ahoywifi { bool getNtpTime(void); void scanAvailNetworks(void); bool getAvailNetworks(JsonObject obj); + void setStopApAllowedMode(bool allowed) { + mStopApAllowed = allowed; + } + String getStationIp(void) { + return WiFi.localIP().toString(); + } + void setupStation(void); private: typedef enum WiFiStatus { @@ -43,7 +50,6 @@ class ahoywifi { void setupWifi(bool startAP); void setupAp(void); - void setupStation(void); void sendNTPpacket(IPAddress& address); void sortRSSI(int *sort, int n); bool getBSSIDs(void); @@ -78,6 +84,7 @@ class ahoywifi { bool mScanActive; bool mGotDisconnect; std::list mBSSIDList; + bool mStopApAllowed; }; #endif /*__AHOYWIFI_H__*/