diff --git a/main/config.h b/main/config.h index 9255b5d..5d53a6f 100644 --- a/main/config.h +++ b/main/config.h @@ -193,6 +193,12 @@ String ap_ssid; String ap_pwd; String ota_pwd; +// WiFi static addresses +String wifi_static_ip; +String wifi_static_gateway_ip; +String wifi_static_subnet; +String wifi_static_dns_ip; + // time and time zone String ntpServer = "pool.ntp.org"; const long gmtOffset_sec = 3600; diff --git a/main/htmls/html_init.h b/main/htmls/html_init.h index 0970a8d..30ef9ec 100644 --- a/main/htmls/html_init.h +++ b/main/htmls/html_init.h @@ -13,7 +13,7 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - + const char html_init_setup[] PROGMEM = "" "
" "

_TXT_INIT_TITLE_

" @@ -41,6 +41,29 @@ const char html_init_setup[] PROGMEM = "" "
" "" "

" + "
" + "Network static IP config" + "

_TXT_WIFI_STATIC_IP_" + "
" + "" + "

" + "

_TXT_WIFI_STATIC_GW_" + "
" + "" + "

" + "

_TXT_WIFI_STATIC_MASK_" + "
" + "" + "

" + "

_TXT_WIFI_STATIC_DNS_" + "
" + "" + "

" + "
" "" "
" "  _TXT_MQTT_TITLE_  
" @@ -71,12 +94,12 @@ const char html_init_setup[] PROGMEM = "" "" "
"; -const char html_init_save[] PROGMEM = +const char html_init_save[] PROGMEM = "

_TXT_INIT_REBOOT_MES_" " _CONFIG_ADDR_" "
" "_TXT_INIT_REBOOT_MES_1_" " 10s...

"; -const char html_init_reboot[] PROGMEM = +const char html_init_reboot[] PROGMEM = "

_TXT_INIT_REBOOT_

"; \ No newline at end of file diff --git a/main/htmls/html_pages.h b/main/htmls/html_pages.h index 8563775..e31e45f 100644 --- a/main/htmls/html_pages.h +++ b/main/htmls/html_pages.h @@ -203,6 +203,27 @@ const char html_page_wifi[] PROGMEM = "" "

" + "

Network static IP config

" + "

_TXT_WIFI_STATIC_IP_" + "
" + "" + "

" + "

_TXT_WIFI_STATIC_GW_" + "
" + "" + "

" + "

_TXT_WIFI_STATIC_MASK_" + "
" + "" + "

" + "

_TXT_WIFI_STATIC_DNS_" + "
" + "" + "

" "
" "" "" diff --git a/main/language_translations.h b/main/language_translations.h index cbd1b5c..4684ef2 100644 --- a/main/language_translations.h +++ b/main/language_translations.h @@ -154,6 +154,11 @@ MAKE_WORD_TRANSLATION(txt_wifi_ssid_enter, en::txt_wifi_ssid_enter, vi::txt_wifi MAKE_WORD_TRANSLATION(txt_wifi_ssid_select, en::txt_wifi_ssid_select, vi::txt_wifi_ssid_select, da::txt_wifi_ssid_select, de::txt_wifi_ssid_select, es::txt_wifi_ssid_select, fr::txt_wifi_ssid_select, it::txt_wifi_ssid_select, ja::txt_wifi_ssid_select, zh::txt_wifi_ssid_select, ca::txt_wifi_ssid_select) // TODO translate MAKE_WORD_TRANSLATION(txt_wifi_psk, en::txt_wifi_psk, vi::txt_wifi_psk, da::txt_wifi_psk, de::txt_wifi_psk, es::txt_wifi_psk, fr::txt_wifi_psk, it::txt_wifi_psk, ja::txt_wifi_psk, zh::txt_wifi_psk, ca::txt_wifi_psk) // TODO translate MAKE_WORD_TRANSLATION(txt_wifi_otap, en::txt_wifi_otap, vi::txt_wifi_otap, da::txt_wifi_otap, de::txt_wifi_otap, es::txt_wifi_otap, fr::txt_wifi_otap, it::txt_wifi_otap, ja::txt_wifi_otap, zh::txt_wifi_otap, ca::txt_wifi_otap) // TODO translate +MAKE_WORD_TRANSLATION(txt_wifi_static_ip, en::txt_wifi_static_ip, vi::txt_wifi_static_ip, da::txt_wifi_static_ip, de::txt_wifi_static_ip, es::txt_wifi_static_ip, fr::txt_wifi_static_ip, it::txt_wifi_static_ip, ja::txt_wifi_static_ip, zh::txt_wifi_static_ip, ca::txt_wifi_static_ip) // TODO translate +MAKE_WORD_TRANSLATION(txt_wifi_static_gw, en::txt_wifi_static_gw, vi::txt_wifi_static_gw, da::txt_wifi_static_gw, de::txt_wifi_static_gw, es::txt_wifi_static_gw, fr::txt_wifi_static_gw, it::txt_wifi_static_gw, ja::txt_wifi_static_gw, zh::txt_wifi_static_gw, ca::txt_wifi_static_gw) // TODO translate +MAKE_WORD_TRANSLATION(txt_wifi_static_mask, en::txt_wifi_static_mask, vi::txt_wifi_static_mask, da::txt_wifi_static_mask, de::txt_wifi_static_mask, es::txt_wifi_static_mask, fr::txt_wifi_static_mask, it::txt_wifi_static_mask, ja::txt_wifi_static_mask, zh::txt_wifi_static_mask, ca::txt_wifi_static_mask) // TODO translate +MAKE_WORD_TRANSLATION(txt_wifi_static_dns, en::txt_wifi_static_dns, vi::txt_wifi_static_dns, da::txt_wifi_static_dns, de::txt_wifi_static_dns, es::txt_wifi_static_dns, fr::txt_wifi_static_dns, it::txt_wifi_static_dns, ja::txt_wifi_static_dns, zh::txt_wifi_static_dns, ca::txt_wifi_static_dns) // TODO translate + // Page Control MAKE_WORD_TRANSLATION(txt_ctrl_title, en::txt_ctrl_title, vi::txt_ctrl_title, da::txt_ctrl_title, de::txt_ctrl_title, es::txt_ctrl_title, fr::txt_ctrl_title, it::txt_ctrl_title, ja::txt_ctrl_title, zh::txt_ctrl_title, ca::txt_ctrl_title) // TODO translate diff --git a/main/languages/ca-ES.h b/main/languages/ca-ES.h index 7e5ce66..44acce1 100644 --- a/main/languages/ca-ES.h +++ b/main/languages/ca-ES.h @@ -124,6 +124,10 @@ namespace ca const char txt_wifi_ssid_select[] PROGMEM = "o trieu una xarxa:"; const char txt_wifi_psk[] PROGMEM = "Contrasenya Wifi"; const char txt_wifi_otap[] PROGMEM = "Contrasenya OTA"; + const char txt_wifi_static_ip[] PROGMEM = "Adreça IP estàtica"; + const char txt_wifi_static_gw[] PROGMEM = "Adreça de passarel·la"; + const char txt_wifi_static_mask[] PROGMEM = "Màscara de xarxa"; + const char txt_wifi_static_dns[] PROGMEM = "Adreça IP DNS"; // Page Control const char txt_ctrl_title[] PROGMEM = "Control climatització"; diff --git a/main/languages/da-DA.h b/main/languages/da-DA.h index d328b73..51c5172 100644 --- a/main/languages/da-DA.h +++ b/main/languages/da-DA.h @@ -123,6 +123,10 @@ namespace da const char txt_wifi_hostname_desc[] PROGMEM = "(no space or special char)"; const char txt_wifi_ssid_enter[] PROGMEM = "(Enter a name)"; const char txt_wifi_ssid_select[] PROGMEM = "or choose a network:"; + const char txt_wifi_static_ip[] PROGMEM = "Static IP address"; + const char txt_wifi_static_gw[] PROGMEM = "Gateway address"; + const char txt_wifi_static_mask[] PROGMEM = "Network mask"; + const char txt_wifi_static_dns[] PROGMEM = "DNS IP address"; // Page Control const char txt_ctrl_title[] PROGMEM = "Control Unit"; diff --git a/main/languages/de-DE.h b/main/languages/de-DE.h index 2ca511a..b38286e 100644 --- a/main/languages/de-DE.h +++ b/main/languages/de-DE.h @@ -123,6 +123,10 @@ namespace de const char txt_wifi_hostname_desc[] PROGMEM = "(no space or special char)"; const char txt_wifi_ssid_enter[] PROGMEM = "(Enter a name)"; const char txt_wifi_ssid_select[] PROGMEM = "or choose a network:"; + const char txt_wifi_static_ip[] PROGMEM = "Static IP address"; + const char txt_wifi_static_gw[] PROGMEM = "Gateway address"; + const char txt_wifi_static_mask[] PROGMEM = "Network mask"; + const char txt_wifi_static_dns[] PROGMEM = "DNS IP address"; // Page Control const char txt_ctrl_title[] PROGMEM = "Kontrolleinheit"; diff --git a/main/languages/en-GB.h b/main/languages/en-GB.h index db185e6..274b7fb 100644 --- a/main/languages/en-GB.h +++ b/main/languages/en-GB.h @@ -124,6 +124,10 @@ namespace en const char txt_wifi_ssid_select[] PROGMEM = "or choose a network:"; const char txt_wifi_psk[] PROGMEM = "Wifi Password"; const char txt_wifi_otap[] PROGMEM = "OTA Password"; + const char txt_wifi_static_ip[] PROGMEM = "Static IP address"; + const char txt_wifi_static_gw[] PROGMEM = "Gateway address"; + const char txt_wifi_static_mask[] PROGMEM = "Network mask"; + const char txt_wifi_static_dns[] PROGMEM = "DNS IP address"; // Page Control const char txt_ctrl_title[] PROGMEM = "Control Unit"; diff --git a/main/languages/es-ES.h b/main/languages/es-ES.h index 4c0bed6..aa1d630 100644 --- a/main/languages/es-ES.h +++ b/main/languages/es-ES.h @@ -124,6 +124,10 @@ namespace es const char txt_wifi_hostname_desc[] PROGMEM = "(no space or special char)"; const char txt_wifi_ssid_enter[] PROGMEM = "(Enter a name)"; const char txt_wifi_ssid_select[] PROGMEM = "or choose a network:"; + const char txt_wifi_static_ip[] PROGMEM = "Dirección IP estática"; + const char txt_wifi_static_gw[] PROGMEM = "Dirección de puerta de enlace"; + const char txt_wifi_static_mask[] PROGMEM = "Máscara de red"; + const char txt_wifi_static_dns[] PROGMEM = "Dirección IP DNS"; // Page Control const char txt_ctrl_title[] PROGMEM = "Control del aparato"; diff --git a/main/languages/fr-FR.h b/main/languages/fr-FR.h index d0568e8..88d20a2 100644 --- a/main/languages/fr-FR.h +++ b/main/languages/fr-FR.h @@ -124,6 +124,10 @@ namespace fr const char txt_wifi_hostname_desc[] PROGMEM = "(no space or special char)"; const char txt_wifi_ssid_enter[] PROGMEM = "(Enter a name)"; const char txt_wifi_ssid_select[] PROGMEM = "or choose a network:"; + const char txt_wifi_static_ip[] PROGMEM = "Adresse IP statique"; + const char txt_wifi_static_gw[] PROGMEM = "Adresse de la passerelle"; + const char txt_wifi_static_mask[] PROGMEM = "Masque de réseau"; + const char txt_wifi_static_dns[] PROGMEM = "Adresse IP DNS"; // Page Control const char txt_ctrl_title[] PROGMEM = "Contrôle climatiseur"; diff --git a/main/languages/it-IT.h b/main/languages/it-IT.h index 8455547..58a8f11 100644 --- a/main/languages/it-IT.h +++ b/main/languages/it-IT.h @@ -124,6 +124,10 @@ namespace it const char txt_wifi_hostname_desc[] PROGMEM = "(no space or special char)"; const char txt_wifi_ssid_enter[] PROGMEM = "(Enter a name)"; const char txt_wifi_ssid_select[] PROGMEM = "or choose a network:"; + const char txt_wifi_static_ip[] PROGMEM = "Static IP address"; + const char txt_wifi_static_gw[] PROGMEM = "Gateway address"; + const char txt_wifi_static_mask[] PROGMEM = "Network mask"; + const char txt_wifi_static_dns[] PROGMEM = "DNS IP address"; // Page Control const char txt_ctrl_title[] PROGMEM = "Controllo Unità"; diff --git a/main/languages/ja-JP.h b/main/languages/ja-JP.h index 412dc4b..bde63c7 100644 --- a/main/languages/ja-JP.h +++ b/main/languages/ja-JP.h @@ -124,6 +124,10 @@ namespace ja const char txt_wifi_hostname_desc[] PROGMEM = "(no space or special char)"; const char txt_wifi_ssid_enter[] PROGMEM = "(Enter a name)"; const char txt_wifi_ssid_select[] PROGMEM = "or choose a network:"; + const char txt_wifi_static_ip[] PROGMEM = "Static IP address"; + const char txt_wifi_static_gw[] PROGMEM = "Gateway address"; + const char txt_wifi_static_mask[] PROGMEM = "Network mask"; + const char txt_wifi_static_dns[] PROGMEM = "DNS IP address"; // Page Control const char txt_ctrl_title[] PROGMEM = "エアコン操作"; diff --git a/main/languages/vi-VN.h b/main/languages/vi-VN.h index 08a7511..ae75c31 100644 --- a/main/languages/vi-VN.h +++ b/main/languages/vi-VN.h @@ -124,6 +124,10 @@ namespace vi const char txt_wifi_ssid_select[] PROGMEM = "hoặc chọn 1 mạng:"; const char txt_wifi_psk[] PROGMEM = "Mật khẩu Wifi"; const char txt_wifi_otap[] PROGMEM = "Mật khẩu OTA"; + const char txt_wifi_static_ip[] PROGMEM = "Địa chỉ IP tĩnh"; + const char txt_wifi_static_gw[] PROGMEM = "Địa chỉ cổng"; + const char txt_wifi_static_mask[] PROGMEM = "Mặt nạ mạng"; + const char txt_wifi_static_dns[] PROGMEM = "Địa chỉ IP DNS"; // Page Control const char txt_ctrl_title[] PROGMEM = "Điều khiển Thiết bị"; diff --git a/main/languages/zh-CN.h b/main/languages/zh-CN.h index 90b80de..d12f080 100644 --- a/main/languages/zh-CN.h +++ b/main/languages/zh-CN.h @@ -124,6 +124,10 @@ namespace zh const char txt_wifi_hostname_desc[] PROGMEM = "(no space or special char)"; const char txt_wifi_ssid_enter[] PROGMEM = "(Enter a name)"; const char txt_wifi_ssid_select[] PROGMEM = "or choose a network:"; + const char txt_wifi_static_ip[] PROGMEM = "Static IP address"; + const char txt_wifi_static_gw[] PROGMEM = "Gateway address"; + const char txt_wifi_static_mask[] PROGMEM = "Network mask"; + const char txt_wifi_static_dns[] PROGMEM = "DNS IP address"; // Page Control const char txt_ctrl_title[] PROGMEM = "控制单元"; diff --git a/main/main.cpp b/main/main.cpp index ccaa61f..91db219 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -334,7 +334,7 @@ bool loadWifi() return false; } // Allocate document capacity. - const size_t capacity = JSON_OBJECT_SIZE(4) + 130; + const size_t capacity = JSON_OBJECT_SIZE(8) + 130 + 4*(16 /*ipv4 addr*/ + 15 /*max key size*/); DynamicJsonDocument doc(capacity); deserializeJson(doc, configFile); // Check key exist to prevent data is "null" @@ -344,7 +344,7 @@ bool loadWifi() } else { - hostname = ""; + hostname.clear(); } if (doc.containsKey("ap_ssid")) { @@ -352,7 +352,7 @@ bool loadWifi() } else { - ap_ssid = ""; + ap_ssid.clear(); } if (doc.containsKey("ap_pwd")) { @@ -360,7 +360,7 @@ bool loadWifi() } else { - ap_pwd = ""; + ap_pwd.clear(); } if (doc.containsKey("ota_pwd")) { @@ -368,8 +368,43 @@ bool loadWifi() } else { - ota_pwd = ""; + ota_pwd.clear(); } + + // static IP configuration + if (doc.containsKey("static_ip")) + { + wifi_static_ip = doc["static_ip"].as(); + } + else + { + wifi_static_ip.clear(); + } + if (doc.containsKey("static_gw_ip")) + { + wifi_static_gateway_ip = doc["static_gw_ip"].as(); + } + else + { + wifi_static_gateway_ip.clear(); + } + if (doc.containsKey("static_subnet")) + { + wifi_static_subnet = doc["static_subnet"].as(); + } + else + { + wifi_static_subnet.clear(); + } + if (doc.containsKey("static_dns_ip")) + { + wifi_static_dns_ip = doc["static_dns_ip"].as(); + } + else + { + wifi_static_dns_ip.clear(); + } + return true; } @@ -668,10 +703,10 @@ void saveUnit(String tempUnit, String supportMode, String supportFanMode, String configFile.close(); } -void saveWifi(String apSsid, const String& apPwd, String hostName, const String& otaPwd) +void saveWifi(String apSsid, const String& apPwd, String hostName, const String& otaPwd, const String& local_ip, const String& gw_ip, const String& subnet_ip, const String& dns_ip) { // Allocate document capacity. - const size_t capacity = JSON_OBJECT_SIZE(4) + 130; + const size_t capacity = JSON_OBJECT_SIZE(8) + 130 + 4*(16 /*ipv4 addr*/ + 15 /*max key size*/); DynamicJsonDocument doc(capacity); if (hostName.isEmpty()) { @@ -681,6 +716,14 @@ void saveWifi(String apSsid, const String& apPwd, String hostName, const String& doc["ap_pwd"] = apPwd; doc["hostname"] = hostName; doc["ota_pwd"] = otaPwd; + if (!local_ip.isEmpty() && !gw_ip.isEmpty() && !subnet_ip.isEmpty()) { + doc["static_ip"] = local_ip; + doc["static_gw_ip"] = gw_ip; + doc["static_subnet"] = subnet_ip; + if (!dns_ip.isEmpty()) { + doc["static_dns_ip"] = dns_ip; + } + } File configFile = SPIFFS.open(wifi_conf, "w"); if (!configFile) { @@ -987,7 +1030,7 @@ void handleSaveWifiAndMqtt(AsyncWebServerRequest *request) { ssid = request->arg("network"); // auto scan network } - saveWifi(ssid, request->arg("psk"), request->arg("hn"), request->arg("otapwd")); + saveWifi(ssid, request->arg("psk"), request->arg("hn"), request->arg("otapwd"), request->arg("stip"), request->arg("stgw"), request->arg("stmask"), request->arg("stdns")); if (request->hasArg("mh")) { saveMqtt(request->arg("fn"), request->arg("mh"), request->arg("ml"), request->arg("mu"), request->arg("mp"), request->arg("mt"), ""); @@ -1063,6 +1106,10 @@ void handleInitSetup(AsyncWebServerRequest *request) initSetupPage.replace("_TXT_WIFI_SSID_SELECT_", translatedWord(FL_(txt_wifi_ssid_select))); initSetupPage.replace("_TXT_WIFI_SSID_", translatedWord(FL_(txt_wifi_ssid))); initSetupPage.replace("_TXT_WIFI_PSK_", translatedWord(FL_(txt_wifi_psk))); + initSetupPage.replace("_TXT_WIFI_STATIC_IP_", translatedWord(FL_(txt_wifi_static_ip))); + initSetupPage.replace("_TXT_WIFI_STATIC_GW_", translatedWord(FL_(txt_wifi_static_gw))); + initSetupPage.replace("_TXT_WIFI_STATIC_MASK_", translatedWord(FL_(txt_wifi_static_mask))); + initSetupPage.replace("_TXT_WIFI_STATIC_DNS_", translatedWord(FL_(txt_wifi_static_dns))); initSetupPage.replace("_TXT_MQTT_TITLE_", translatedWord(FL_(txt_mqtt_title))); initSetupPage.replace("_TXT_MQTT_PH_USER_", translatedWord(FL_(txt_mqtt_ph_user))); initSetupPage.replace("_TXT_MQTT_PH_PWD_", translatedWord(FL_(txt_mqtt_ph_pwd))); @@ -1347,7 +1394,7 @@ void handleWifi(AsyncWebServerRequest *request) ssid = request->arg("network"); // auto scan network } ESP_LOGD(TAG, "handleWifi: %s", ssid.c_str()); - saveWifi(ssid, request->arg("psk"), request->arg("hn"), request->arg("otapwd")); + saveWifi(ssid, request->arg("psk"), request->arg("hn"), request->arg("otapwd"), request->arg("stip"), request->arg("stgw"), request->arg("stmask"), request->arg("stdns")); String saveRebootPage = FPSTR(html_page_save_reboot); // localize saveRebootPage.replace("_TXT_M_SAVE_", translatedWord(FL_(txt_m_save))); @@ -1372,6 +1419,10 @@ void handleWifi(AsyncWebServerRequest *request) wifiPage.replace("_TXT_WIFI_SSID_", translatedWord(FL_(txt_wifi_ssid))); wifiPage.replace("_TXT_WIFI_PSK_", translatedWord(FL_(txt_wifi_psk))); wifiPage.replace("_TXT_WIFI_OTAP_", translatedWord(FL_(txt_wifi_otap))); + wifiPage.replace("_TXT_WIFI_STATIC_IP_", translatedWord(FL_(txt_wifi_static_ip))); + wifiPage.replace("_TXT_WIFI_STATIC_GW_", translatedWord(FL_(txt_wifi_static_gw))); + wifiPage.replace("_TXT_WIFI_STATIC_MASK_", translatedWord(FL_(txt_wifi_static_mask))); + wifiPage.replace("_TXT_WIFI_STATIC_DNS_", translatedWord(FL_(txt_wifi_static_dns))); wifiPage.replace("_TXT_SAVE_", translatedWord(FL_(txt_save))); wifiPage.replace("_TXT_BACK_", translatedWord(FL_(txt_back))); // set data @@ -1390,6 +1441,10 @@ void handleWifi(AsyncWebServerRequest *request) wifiPage.replace(F("_SSID_"), str_ap_ssid); wifiPage.replace(F("_PSK_"), str_ap_pwd); wifiPage.replace(F("_OTA_PWD_"), str_ota_pwd); + wifiPage.replace(F("_WIFI_STATIC_IP_"), wifi_static_ip); + wifiPage.replace(F("_WIFI_STATIC_GW_"), wifi_static_gateway_ip); + wifiPage.replace(F("_WIFI_STATIC_MASK_"), wifi_static_subnet); + wifiPage.replace(F("_WIFI_STATIC_DNS_"), wifi_static_dns_ip); String fwCheckEvents = FPSTR(fw_check_script_events); sendWrappedHTML(request, fwCheckEvents + wifiPage); } @@ -2883,6 +2938,33 @@ bool connectWifi() WiFi.mode(WIFI_STA); delay(100); } + bool static_valid = true; + IPAddress local_ip, gw_ip, subnet_ip, dns_ip; + if (static_valid && !local_ip.fromString(wifi_static_ip)) { + static_valid = false; + } + if (static_valid && !gw_ip.fromString(wifi_static_gateway_ip)) { + static_valid = false; + } + if (static_valid && !subnet_ip.fromString(wifi_static_subnet)) { + static_valid = false; + } + if (static_valid) { + if (wifi_static_dns_ip.isEmpty()) { + dns_ip = gw_ip; + } else if (!dns_ip.fromString(wifi_static_dns_ip)) { + static_valid = false; + } + } + + bool ok = false; + if (static_valid) { + ok = WiFi.config(local_ip, gw_ip, subnet_ip, dns_ip); + } + if (!ok || !static_valid) { + // fallback to DHCP + WiFi.config(0, 0, 0); + } WiFi.begin(ap_ssid.c_str(), ap_pwd.c_str()); ESP_LOGD(TAG, "Connected to %s", ap_ssid.c_str()); wifi_timeout = millis() + 30000; @@ -3611,6 +3693,7 @@ String getValueBySeparator(const String& data, char separator, int index) void factoryReset() { SPIFFS.format(); + WiFi.disconnect(true, true); #ifdef ESP32 // delete nvs partition because AP mode not working if have other data esp_err_t err = nvs_flash_erase();