diff --git a/tools/esp8266/ahoywifi.cpp b/tools/esp8266/ahoywifi.cpp index 38863e05..7a78cec0 100644 --- a/tools/esp8266/ahoywifi.cpp +++ b/tools/esp8266/ahoywifi.cpp @@ -141,6 +141,14 @@ bool ahoywifi::setupStation(uint32_t timeout) { } WiFi.mode(WIFI_STA); + if(mConfig->staticIp.ip[0] != 0) { + IPAddress ip(mConfig->staticIp.ip); + IPAddress mask(mConfig->staticIp.mask); + IPAddress dns(mConfig->staticIp.dns); + IPAddress gateway(mConfig->staticIp.gateway); + if(!WiFi.config(ip, gateway, mask, dns)) + DPRINTLN(DBG_ERROR, F("failed to set static IP!")); + } WiFi.begin(mSysCfg->stationSsid, mSysCfg->stationPwd); if(String(mSysCfg->deviceName) != "") WiFi.hostname(mSysCfg->deviceName); diff --git a/tools/esp8266/defines.h b/tools/esp8266/defines.h index b3bc8a2f..eb1163ce 100644 --- a/tools/esp8266/defines.h +++ b/tools/esp8266/defines.h @@ -126,6 +126,17 @@ typedef struct { #pragma pack(pop) // restore original alignment from stack +#pragma pack(push) // push current alignment to stack +#pragma pack(1) // set alignment to 1 byte boundary +typedef struct { + uint8_t ip[4]; // ip address + uint8_t mask[4]; // sub mask + uint8_t dns[4]; // dns + uint8_t gateway[4]; // standard gateway +} staticIp_t; +#pragma pack(pop) // restore original alignment from stack + + #pragma pack(push) // push current alignment to stack #pragma pack(1) // set alignment to 1 byte boundary typedef struct { @@ -160,8 +171,8 @@ typedef struct { bool serialShowIv; bool serialDebug; - // static ip placeholder - uint32_t staticIp[4]; + // static ip + staticIp_t staticIp; } config_t; #pragma pack(pop) // restore original alignment from stack diff --git a/tools/esp8266/html/setup.html b/tools/esp8266/html/setup.html index 6dac4c84..4a9b70ef 100644 --- a/tools/esp8266/html/setup.html +++ b/tools/esp8266/html/setup.html @@ -57,6 +57,21 @@ +
+ Static IP (optional) +

+ Leave fields blank for DHCP
+ The following fields are parsed in this format: 192.168.1.1 +

+ + + + + + + + +
@@ -92,6 +107,9 @@
Sunrise & Sunset +

+ Latitude and Longitude must be set to be stored! decimal separator: '.' (dot) +

@@ -313,6 +331,12 @@ parseVersion(obj); } + function parseStaticIp(obj) { + for(var i of [["ipAddr", "ip"], ["ipMask", "mask"], ["ipDns", "dns"], ["ipGateway", "gateway"]]) + if(null != obj[i[1]]) + document.getElementsByName(i[0])[0].value = obj[i[1]]; + } + function parseIv(obj) { for(var i = 0; i < obj.inverter.length; i++) ivHtml(obj.inverter[i], i); @@ -416,6 +440,7 @@ if(null != root) { parseMenu(root["menu"]); parseSys(root["system"]); + parseStaticIp(root["static_ip"]); parseIv(root["inverter"]); parseMqtt(root["mqtt"]); parseNtp(root["ntp"]); diff --git a/tools/esp8266/web.cpp b/tools/esp8266/web.cpp index d91cdc4e..8f1a7659 100644 --- a/tools/esp8266/web.cpp +++ b/tools/esp8266/web.cpp @@ -330,6 +330,28 @@ void web::showSave(AsyncWebServerRequest *request) { mProtected = (strlen(mConfig->password) > 0); } + + // static ip + if(request->arg("ipAddr") != "") { + request->arg("ipAddr").toCharArray(buf, SSID_LEN); + ip2Arr(mConfig->staticIp.ip, buf); + if(request->arg("ipMask") != "") { + request->arg("ipMask").toCharArray(buf, SSID_LEN); + ip2Arr(mConfig->staticIp.mask, buf); + } + if(request->arg("ipDns") != "") { + request->arg("ipDns").toCharArray(buf, SSID_LEN); + ip2Arr(mConfig->staticIp.dns, buf); + } + if(request->arg("ipGateway") != "") { + request->arg("ipGateway").toCharArray(buf, SSID_LEN); + ip2Arr(mConfig->staticIp.gateway, buf); + } + } + else + memset(&mConfig->staticIp, 0, sizeof(staticIp_t)); + + // inverter Inverter<> *iv; for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) { diff --git a/tools/esp8266/web.h b/tools/esp8266/web.h index 85bee0b8..2bb9f918 100644 --- a/tools/esp8266/web.h +++ b/tools/esp8266/web.h @@ -61,6 +61,15 @@ class web { void onSerial(AsyncWebServerRequest *request); void onSystem(AsyncWebServerRequest *request); + void ip2Arr(uint8_t ip[], char *ipStr) { + char *p = strtok(ipStr, "."); + uint8_t i = 0; + while(NULL != p) { + ip[i++] = atoi(p); + p = strtok(NULL, "."); + } + } + AsyncWebServer *mWeb; AsyncEventSource *mEvts; bool mProtected; diff --git a/tools/esp8266/webApi.cpp b/tools/esp8266/webApi.cpp index 01584f46..2e3e9000 100644 --- a/tools/esp8266/webApi.cpp +++ b/tools/esp8266/webApi.cpp @@ -284,6 +284,17 @@ void webApi::getSerial(JsonObject obj) { } +//----------------------------------------------------------------------------- +void webApi::getStaticIp(JsonObject obj) { + if(mConfig->staticIp.ip[0] != 0) { + obj[F("ip")] = ip2String(mConfig->staticIp.ip); + obj[F("mask")] = ip2String(mConfig->staticIp.mask); + obj[F("dns")] = ip2String(mConfig->staticIp.dns); + obj[F("gateway")] = ip2String(mConfig->staticIp.gateway); + } +} + + //----------------------------------------------------------------------------- void webApi::getMenu(JsonObject obj) { obj["name"][0] = "Live"; @@ -359,6 +370,7 @@ void webApi::getSetup(JsonObject obj) { getPinout(obj.createNestedObject(F("pinout"))); getRadio(obj.createNestedObject(F("radio"))); getSerial(obj.createNestedObject(F("serial"))); + getStaticIp(obj.createNestedObject(F("static_ip"))); } diff --git a/tools/esp8266/webApi.h b/tools/esp8266/webApi.h index d871fd01..252b7c4c 100644 --- a/tools/esp8266/webApi.h +++ b/tools/esp8266/webApi.h @@ -45,6 +45,7 @@ class webApi { void getPinout(JsonObject obj); void getRadio(JsonObject obj); void getSerial(JsonObject obj); + void getStaticIp(JsonObject obj); void getMenu(JsonObject obj); void getIndex(JsonObject obj); @@ -62,6 +63,12 @@ class webApi { return (int)(value * 1000 + 0.5) / 1000.0; } + String ip2String(uint8_t ip[]) { + char str[16]; + snprintf(str, 16, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + return String(str); + } + AsyncWebServer *mSrv; app *mApp;