Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added multi WiFi saving feature #3705

Closed
wants to merge 13 commits into from
153 changes: 116 additions & 37 deletions wled00/cfg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@
//simple macro for ArduinoJSON's or syntax
#define CJSON(a,b) a = b | a

void clearSavedWiFiNetworks() {
cfg_wifi_network_t *tmp_item;
while (savedWiFiNetworks != nullptr) {
tmp_item = savedWiFiNetworks;
savedWiFiNetworks = tmp_item->Next;
free(tmp_item);
}
}

void getStringFromJson(char* dest, const char* src, size_t len) {
if (src != nullptr) strlcpy(dest, src, len);
}
Expand Down Expand Up @@ -40,21 +49,67 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
linked_remote[12] = '\0';
#endif

JsonObject nw_ins_0 = nw["ins"][0];
getStringFromJson(clientSSID, nw_ins_0[F("ssid")], 33);
//int nw_ins_0_pskl = nw_ins_0[F("pskl")];
//The WiFi PSK is normally not contained in the regular file for security reasons.
//If it is present however, we will use it
getStringFromJson(clientPass, nw_ins_0["psk"], 65);
JsonArray nw_ins = nw["ins"];
clearSavedWiFiNetworks();
bool needLoadIPs = true;
if (nw_ins.isNull()) {
savedWiFiNetworks = cfg_wifi_network_t::createItem(CLIENT_SSID, CLIENT_PASS);
needsSave = true;
} else {
char tmp_ssid[WIFI_MAX_SSID_LENGTH + 1];
char tmp_pass[WIFI_MAX_PASS_LENGTH + 1];
cfg_wifi_network_t *last_item;
for (JsonObject wifi : nw_ins) {
if (wifi.containsKey(F("ip")) || wifi.containsKey(F("gw")) || wifi.containsKey(F("sn"))) {
JsonArray wifi_ip = wifi["ip"];
JsonArray wifi_gw = wifi["gw"];
JsonArray wifi_sn = wifi["sn"];

for (byte i = 0; i < 4; i++) {
CJSON(staticIP[i], wifi_ip[i]);
CJSON(staticGateway[i], wifi_gw[i]);
CJSON(staticSubnet[i], wifi_sn[i]);
}

needLoadIPs = false;
needsSave = true;
}

JsonArray nw_ins_0_ip = nw_ins_0["ip"];
JsonArray nw_ins_0_gw = nw_ins_0["gw"];
JsonArray nw_ins_0_sn = nw_ins_0["sn"];
if (!wifi.containsKey(F("ssid")))
continue;
getStringFromJson(tmp_ssid, wifi[F("ssid")], WIFI_MAX_SSID_LENGTH + 1);
//int nw_ins_0_pskl = nw_ins_0[F("pskl")];
//The WiFi PSK is normally not contained in the regular file for security reasons.
//If it is present however, we will use it
if (wifi.containsKey(F("psk"))) {
getStringFromJson(tmp_pass, wifi[F("psk")], WIFI_MAX_PASS_LENGTH + 1);
} else {
memset(tmp_pass, 0, WIFI_MAX_PASS_LENGTH + 1);
}

for (byte i = 0; i < 4; i++) {
CJSON(staticIP[i], nw_ins_0_ip[i]);
CJSON(staticGateway[i], nw_ins_0_gw[i]);
CJSON(staticSubnet[i], nw_ins_0_sn[i]);
cfg_wifi_network_t *new_wifi = cfg_wifi_network_t::createItem(tmp_ssid, tmp_pass);
if (savedWiFiNetworks == nullptr) {
savedWiFiNetworks = new_wifi;
} else {
//NOTE: The following line may warn about last_item not being uninitialized.
// It's safe to ignore it.
last_item->Next = new_wifi;
}
last_item = new_wifi;
}
}

if (needLoadIPs) {
JsonObject nw_net_0 = nw["net"][0];
JsonArray nw_net_0_ip = nw_net_0["ip"];
JsonArray nw_net_0_gw = nw_net_0["gw"];
JsonArray nw_net_0_sn = nw_net_0["sn"];

for (byte i = 0; i < 4; i++) {
CJSON(staticIP[i], nw_net_0_ip[i]);
CJSON(staticGateway[i], nw_net_0_gw[i]);
CJSON(staticSubnet[i], nw_net_0_sn[i]);
}
}

JsonObject ap = doc["ap"];
Expand Down Expand Up @@ -597,19 +652,11 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
}

void deserializeConfigFromFS() {
bool success = deserializeConfigSec();
if (!success) { //if file does not exist, try reading from EEPROM
#ifdef WLED_ADD_EEPROM_SUPPORT
deEEPSettings();
return;
#endif
}

if (!requestJSONBufferLock(1)) return;

DEBUG_PRINTLN(F("Reading settings from /cfg.json..."));

success = readObjectFromFile("/cfg.json", nullptr, pDoc);
bool success = readObjectFromFile("/cfg.json", nullptr, pDoc);
if (!success) { // if file does not exist, optionally try reading from EEPROM and then save defaults to FS
releaseJSONBufferLock();
#ifdef WLED_ADD_EEPROM_SUPPORT
Expand All @@ -634,6 +681,13 @@ void deserializeConfigFromFS() {
bool needsSave = deserializeConfig(root, true);
releaseJSONBufferLock();

success = deserializeConfigSec();
if (!success) { //if file does not exist, try reading from EEPROM
#ifdef WLED_ADD_EEPROM_SUPPORT
deEEPSettings();
#endif
}

if (needsSave) serializeConfig(); // usermods required new parameters
}

Expand Down Expand Up @@ -665,19 +719,24 @@ void serializeConfig() {
#endif

JsonArray nw_ins = nw.createNestedArray("ins");
cfg_wifi_network_t *tmp_item = savedWiFiNetworks;
JsonObject tmp_json;
while (tmp_item != nullptr) {
tmp_json = nw_ins.createNestedObject();
tmp_json["ssid"] = tmp_item->SSID;
tmp_json["pskl"] = strlen(tmp_item->Pass);
tmp_item = tmp_item->Next;
}

JsonObject nw_ins_0 = nw_ins.createNestedObject();
nw_ins_0[F("ssid")] = clientSSID;
nw_ins_0[F("pskl")] = strlen(clientPass);

JsonArray nw_ins_0_ip = nw_ins_0.createNestedArray("ip");
JsonArray nw_ins_0_gw = nw_ins_0.createNestedArray("gw");
JsonArray nw_ins_0_sn = nw_ins_0.createNestedArray("sn");
JsonObject nw_net_0 = nw.createNestedArray("net").createNestedObject();
JsonArray nw_net_0_ip = nw_net_0.createNestedArray("ip");
JsonArray nw_net_0_gw = nw_net_0.createNestedArray("gw");
JsonArray nw_net_0_sn = nw_net_0.createNestedArray("sn");

for (byte i = 0; i < 4; i++) {
nw_ins_0_ip.add(staticIP[i]);
nw_ins_0_gw.add(staticGateway[i]);
nw_ins_0_sn.add(staticSubnet[i]);
nw_net_0_ip.add(staticIP[i]);
nw_net_0_gw.add(staticGateway[i]);
nw_net_0_sn.add(staticSubnet[i]);
}

JsonObject ap = root.createNestedObject("ap");
Expand Down Expand Up @@ -1048,8 +1107,24 @@ bool deserializeConfigSec() {

JsonObject root = pDoc->as<JsonObject>();

JsonObject nw_ins_0 = root["nw"]["ins"][0];
getStringFromJson(clientPass, nw_ins_0["psk"], 65);
JsonArray nw_ins = root["nw"]["ins"];
if (!nw_ins.isNull()) {
char tmp_pass[WIFI_MAX_PASS_LENGTH + 1];
cfg_wifi_network_t *last_item = savedWiFiNetworks;
for (JsonObject wifi : nw_ins) {
if (last_item == nullptr) break;
if (wifi.containsKey(F("psk")))
{
getStringFromJson(tmp_pass, wifi[F("psk")], WIFI_MAX_PASS_LENGTH + 1);
if (last_item->Pass != nullptr) free(last_item->Pass);
last_item->Pass_Length = strlen(tmp_pass);
if (last_item->Pass_Length > WIFI_MAX_PASS_LENGTH) last_item->Pass_Length = WIFI_MAX_PASS_LENGTH;
last_item->Pass = (char*)calloc(last_item->Pass_Length + 1, sizeof(char));
strncpy(last_item->Pass, tmp_pass, last_item->Pass_Length + 1);
}
last_item = last_item->Next;
}
}

JsonObject ap = root["ap"];
getStringFromJson(apPass, ap["psk"] , 65);
Expand Down Expand Up @@ -1088,9 +1163,13 @@ void serializeConfigSec() {
JsonObject nw = root.createNestedObject("nw");

JsonArray nw_ins = nw.createNestedArray("ins");

JsonObject nw_ins_0 = nw_ins.createNestedObject();
nw_ins_0["psk"] = clientPass;
cfg_wifi_network_t *tmp_item = savedWiFiNetworks;
JsonObject tmp_json;
while (tmp_item != nullptr) {
tmp_json = nw_ins.createNestedObject();
tmp_json["psk"] = tmp_item->Pass;
tmp_item = tmp_item->Next;
}

JsonObject ap = root.createNestedObject("ap");
ap["psk"] = apPass;
Expand Down
8 changes: 8 additions & 0 deletions wled00/const.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@
#endif
#endif

#define WIFI_MAX_SSID_LENGTH 32
#define WIFI_MAX_PASS_LENGTH 64

// This max was selected arbitrarily. Should be adjusted for real-world cases
#ifndef WLED_MAX_SAVED_NETWORKS
#define WLED_MAX_SAVED_NETWORKS 3
#endif

//Usermod IDs
#define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present
#define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID
Expand Down
Loading
Loading