diff --git a/library.json b/library.json index 2461bdde..f3181cfd 100644 --- a/library.json +++ b/library.json @@ -22,7 +22,7 @@ "dependencies": [ { "name": "ArduinoJson", - "version": "^5.10.0" + "version": "^6.11.4" }, { "name": "AsyncMqttClient", diff --git a/src/Homie/Boot/BootConfig.cpp b/src/Homie/Boot/BootConfig.cpp index d2c661a7..34c91afa 100644 --- a/src/Homie/Boot/BootConfig.cpp +++ b/src/Homie/Boot/BootConfig.cpp @@ -121,14 +121,14 @@ void BootConfig::loop() { void BootConfig::_onWifiConnectRequest(AsyncWebServerRequest *request) { Interface::get().getLogger() << F("Received Wi-Fi connect request") << endl; - DynamicJsonBuffer parseJsonBuffer(JSON_OBJECT_SIZE(2)); - const char* body = (const char*)(request->_tempObject); - JsonObject& parsedJson = parseJsonBuffer.parseObject(body); - if (!parsedJson.success()) { + StaticJsonDocument parseJsonDoc; + char* body = reinterpret_cast(request->_tempObject); + if (deserializeJson(parseJsonDoc, body) != DeserializationError::Ok || !parseJsonDoc.is()) { __SendJSONError(request, F("✖ Invalid or too big JSON")); return; } + JsonObject parsedJson = parseJsonDoc.as(); if (!parsedJson.containsKey("ssid") || !parsedJson["ssid"].is() || !parsedJson.containsKey("password") || !parsedJson["password"].is()) { __SendJSONError(request, F("✖ SSID and password required")); return; @@ -143,11 +143,11 @@ void BootConfig::_onWifiConnectRequest(AsyncWebServerRequest *request) { void BootConfig::_onWifiStatusRequest(AsyncWebServerRequest *request) { Interface::get().getLogger() << F("Received Wi-Fi status request") << endl; - DynamicJsonBuffer generatedJsonBuffer(JSON_OBJECT_SIZE(2)); - JsonObject& json = generatedJsonBuffer.createObject(); + // Includes memory to duplicate strings for status ("no_ssid_available" -> 18) and local_ip (IPv4 -> 16) + StaticJsonDocument generatedJsonDoc; + JsonObject json = generatedJsonDoc.to(); String status; - //String json = ""; switch (WiFi.status()) { case WL_IDLE_STATUS: status = F("idle"); @@ -175,21 +175,21 @@ void BootConfig::_onWifiStatusRequest(AsyncWebServerRequest *request) { json["status"] = status; String output; - json.printTo(output); + serializeJson(generatedJsonDoc, output); request->send(200, FPSTR(PROGMEM_CONFIG_APPLICATION_JSON), output); } void BootConfig::_onProxyControlRequest(AsyncWebServerRequest *request) { Interface::get().getLogger() << F("Received proxy control request") << endl; - DynamicJsonBuffer parseJsonBuffer(JSON_OBJECT_SIZE(1)); - const char* body = (const char*)(request->_tempObject); - JsonObject& parsedJson = parseJsonBuffer.parseObject(body); // do not use plain String, else fails - if (!parsedJson.success()) { + StaticJsonDocument parseJsonDoc; + char* body = reinterpret_cast(request->_tempObject); + if (deserializeJson(parseJsonDoc, body) != DeserializationError::Ok || !parseJsonDoc.is()) { __SendJSONError(request, F("✖ Invalid or too big JSON")); return; } + JsonObject parsedJson = parseJsonDoc.as(); if (!parsedJson.containsKey("enable") || !parsedJson["enable"].is()) { __SendJSONError(request, F("✖ enable parameter is required")); return; @@ -201,12 +201,16 @@ void BootConfig::_onProxyControlRequest(AsyncWebServerRequest *request) { } void BootConfig::_generateNetworksJson() { - DynamicJsonBuffer generatedJsonBuffer(JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(_ssidCount) + (_ssidCount * JSON_OBJECT_SIZE(3))); // 1 at root, 3 in childrend - JsonObject& json = generatedJsonBuffer.createObject(); - - JsonArray& networks = json.createNestedArray("networks"); + DynamicJsonDocument generatedJsonDoc( + JSON_OBJECT_SIZE(1) + // Root object + JSON_ARRAY_SIZE(_ssidCount) + // Array "networks" + _ssidCount * JSON_OBJECT_SIZE(3) + // Objects in "networks" + _ssidCount * (32 + 1)); // SSID strings are duplicated and take up to 32 bytes + terminator + JsonObject json = generatedJsonDoc.to(); + + JsonArray networks = json.createNestedArray("networks"); for (int network = 0; network < _ssidCount; network++) { - JsonObject& jsonNetwork = generatedJsonBuffer.createObject(); + JsonObject jsonNetwork = networks.createNestedObject(); jsonNetwork["ssid"] = WiFi.SSID(network); jsonNetwork["rssi"] = WiFi.RSSI(network); #ifdef ESP32 @@ -249,12 +253,10 @@ void BootConfig::_generateNetworksJson() { break; } #endif // ESP32 - - networks.add(jsonNetwork); } String output; - json.printTo(output); + serializeJson(generatedJsonDoc, output); _jsonWifiNetworks = output; } @@ -320,7 +322,7 @@ void BootConfig::_proxyHttpRequest(AsyncWebServerRequest *request) { } Interface::get().getLogger() << F("Proxy sent request to destination") << endl; - const char* body = (const char*)(request->_tempObject); + const char* body = reinterpret_cast(request->_tempObject); int _httpCode = _httpClient.sendRequest(method.c_str(), body); Interface::get().getLogger() << F("Destination response code = ") << _httpCode << endl; @@ -339,25 +341,30 @@ void BootConfig::_onDeviceInfoRequest(AsyncWebServerRequest *request) { Interface::get().getLogger() << F("Received device information request") << endl; auto numSettings = IHomieSetting::settings.size(); auto numNodes = HomieNode::nodes.size(); - DynamicJsonBuffer jsonBuffer(JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(2) + JSON_ARRAY_SIZE(numNodes) + (numNodes * JSON_OBJECT_SIZE(2)) + JSON_ARRAY_SIZE(numSettings) + (numSettings * JSON_OBJECT_SIZE(5))); - JsonObject& json = jsonBuffer.createObject(); + DynamicJsonDocument jsonDoc( + JSON_OBJECT_SIZE(5) + // Root object + JSON_OBJECT_SIZE(2) + // Object "firmware" + JSON_ARRAY_SIZE(numNodes) + // Array "nodes" + JSON_OBJECT_SIZE(2) * numNodes + // Objects in "nodes" + JSON_ARRAY_SIZE(numSettings) + // Array "settings" + numSettings * JSON_OBJECT_SIZE(5)); // Objects in "settings" + JsonObject json = jsonDoc.to(); json["hardware_device_id"] = DeviceId::get(); json["homie_esp8266_version"] = HOMIE_ESP8266_VERSION; - JsonObject& firmware = json.createNestedObject("firmware"); - firmware["name"] = Interface::get().firmware.name; - firmware["version"] = Interface::get().firmware.version; + JsonObject firmware = json.createNestedObject("firmware"); + firmware["name"] = reinterpret_cast(Interface::get().firmware.name); + firmware["version"] = reinterpret_cast(Interface::get().firmware.version); - JsonArray& nodes = json.createNestedArray("nodes"); + JsonArray nodes = json.createNestedArray("nodes"); for (HomieNode* iNode : HomieNode::nodes) { - JsonObject& jsonNode = jsonBuffer.createObject(); + JsonObject jsonNode = nodes.createNestedObject(); jsonNode["id"] = iNode->getId(); jsonNode["type"] = iNode->getType(); - nodes.add(jsonNode); } - JsonArray& settings = json.createNestedArray("settings"); + JsonArray settings = json.createNestedArray("settings"); for (IHomieSetting* iSetting : IHomieSetting::settings) { - JsonObject& jsonSetting = jsonBuffer.createObject(); + JsonObject jsonSetting = settings.createNestedObject(); if (strcmp(iSetting->getType(), "unknown") != 0) { jsonSetting["name"] = iSetting->getName(); @@ -381,12 +388,10 @@ void BootConfig::_onDeviceInfoRequest(AsyncWebServerRequest *request) { } } } - - settings.add(jsonSetting); } String output; - json.printTo(output); + serializeJson(jsonDoc, output); request->send(200, FPSTR(PROGMEM_CONFIG_APPLICATION_JSON), output); } @@ -407,14 +412,15 @@ void BootConfig::_onConfigRequest(AsyncWebServerRequest *request) { return; } - DynamicJsonBuffer parseJsonBuffer(MAX_JSON_CONFIG_ARDUINOJSON_BUFFER_SIZE); - const char* body = (const char*)(request->_tempObject); - JsonObject& parsedJson = parseJsonBuffer.parseObject(body); - if (!parsedJson.success()) { + DynamicJsonDocument parseJsonDoc(MAX_JSON_CONFIG_ARDUINOJSON_BUFFER_SIZE); + char* body = reinterpret_cast(request->_tempObject); + if (deserializeJson(parseJsonDoc, body) != DeserializationError::Ok || !parseJsonDoc.is()) { __SendJSONError(request, F("✖ Invalid or too big JSON")); return; } + JsonObject parsedJson = parseJsonDoc.as(); + ConfigValidationResult configValidationResult = Validation::validateConfig(parsedJson); if (!configValidationResult.valid) { __SendJSONError(request, String(F("✖ Config file is not valid, reason: ")) + configValidationResult.reason); diff --git a/src/Homie/Config.cpp b/src/Homie/Config.cpp index 38a34ea5..87735702 100644 --- a/src/Homie/Config.cpp +++ b/src/Homie/Config.cpp @@ -49,13 +49,13 @@ bool Config::load() { configFile.close(); buf[configSize] = '\0'; - StaticJsonBuffer jsonBuffer; - JsonObject& parsedJson = jsonBuffer.parseObject(buf); - if (!parsedJson.success()) { + StaticJsonDocument jsonDoc; + if (deserializeJson(jsonDoc, buf) != DeserializationError::Ok || !jsonDoc.is()) { Interface::get().getLogger() << F("✖ Invalid JSON in the config file") << endl; return false; } + JsonObject parsedJson = jsonDoc.as(); ConfigValidationResult configValidationResult = Validation::validateConfig(parsedJson); if (!configValidationResult.valid) { Interface::get().getLogger() << F("✖ Config file is not valid, reason: ") << configValidationResult.reason << endl; @@ -77,65 +77,65 @@ bool Config::load() { } const char* reqWifiBssid = ""; - if (parsedJson["wifi"].as().containsKey("bssid")) { + if (parsedJson["wifi"].as().containsKey("bssid")) { reqWifiBssid = parsedJson["wifi"]["bssid"]; } uint16_t reqWifiChannel = 0; - if (parsedJson["wifi"].as().containsKey("channel")) { + if (parsedJson["wifi"].as().containsKey("channel")) { reqWifiChannel = parsedJson["wifi"]["channel"]; } const char* reqWifiIp = ""; - if (parsedJson["wifi"].as().containsKey("ip")) { + if (parsedJson["wifi"].as().containsKey("ip")) { reqWifiIp = parsedJson["wifi"]["ip"]; } const char* reqWifiMask = ""; - if (parsedJson["wifi"].as().containsKey("mask")) { + if (parsedJson["wifi"].as().containsKey("mask")) { reqWifiMask = parsedJson["wifi"]["mask"]; } const char* reqWifiGw = ""; - if (parsedJson["wifi"].as().containsKey("gw")) { + if (parsedJson["wifi"].as().containsKey("gw")) { reqWifiGw = parsedJson["wifi"]["gw"]; } const char* reqWifiDns1 = ""; - if (parsedJson["wifi"].as().containsKey("dns1")) { + if (parsedJson["wifi"].as().containsKey("dns1")) { reqWifiDns1 = parsedJson["wifi"]["dns1"]; } const char* reqWifiDns2 = ""; - if (parsedJson["wifi"].as().containsKey("dns2")) { + if (parsedJson["wifi"].as().containsKey("dns2")) { reqWifiDns2 = parsedJson["wifi"]["dns2"]; } uint16_t reqMqttPort = DEFAULT_MQTT_PORT; - if (parsedJson["mqtt"].as().containsKey("port")) { + if (parsedJson["mqtt"].as().containsKey("port")) { reqMqttPort = parsedJson["mqtt"]["port"]; } bool reqMqttSsl = false; - if (parsedJson["mqtt"].as().containsKey("ssl")) { + if (parsedJson["mqtt"].as().containsKey("ssl")) { reqMqttSsl = parsedJson["mqtt"]["ssl"]; } const char* reqMqttFingerprint = ""; - if (parsedJson["mqtt"].as().containsKey("ssl_fingerprint")) { + if (parsedJson["mqtt"].as().containsKey("ssl_fingerprint")) { reqMqttFingerprint = parsedJson["mqtt"]["ssl_fingerprint"]; } const char* reqMqttBaseTopic = DEFAULT_MQTT_BASE_TOPIC; - if (parsedJson["mqtt"].as().containsKey("base_topic")) { + if (parsedJson["mqtt"].as().containsKey("base_topic")) { reqMqttBaseTopic = parsedJson["mqtt"]["base_topic"]; } bool reqMqttAuth = false; - if (parsedJson["mqtt"].as().containsKey("auth")) { + if (parsedJson["mqtt"].as().containsKey("auth")) { reqMqttAuth = parsedJson["mqtt"]["auth"]; } const char* reqMqttUsername = ""; - if (parsedJson["mqtt"].as().containsKey("username")) { + if (parsedJson["mqtt"].as().containsKey("username")) { reqMqttUsername = parsedJson["mqtt"]["username"]; } const char* reqMqttPassword = ""; - if (parsedJson["mqtt"].as().containsKey("password")) { + if (parsedJson["mqtt"].as().containsKey("password")) { reqMqttPassword = parsedJson["mqtt"]["password"]; } bool reqOtaEnabled = false; - if (parsedJson["ota"].as().containsKey("enabled")) { + if (parsedJson["ota"].as().containsKey("enabled")) { reqOtaEnabled = parsedJson["ota"]["enabled"]; } @@ -168,7 +168,7 @@ bool Config::load() { /* Parse the settings */ - JsonObject& settingsObject = parsedJson["settings"].as(); + JsonObject settingsObject = parsedJson["settings"].as(); for (IHomieSetting* iSetting : IHomieSetting::settings) { if (iSetting->isBool()) { @@ -211,16 +211,16 @@ char* Config::getSafeConfigFile() const { configFile.close(); buf[configSize] = '\0'; - StaticJsonBuffer jsonBuffer; - JsonObject& parsedJson = jsonBuffer.parseObject(buf); - parsedJson["wifi"].as().remove("password"); - parsedJson["mqtt"].as().remove("username"); - parsedJson["mqtt"].as().remove("password"); + StaticJsonDocument jsonDoc; + deserializeJson(jsonDoc, buf); + JsonObject parsedJson = jsonDoc.as(); + parsedJson["wifi"].as().remove("password"); + parsedJson["mqtt"].as().remove("username"); + parsedJson["mqtt"].as().remove("password"); - size_t jsonBufferLength = parsedJson.measureLength() + 1; + size_t jsonBufferLength = measureJson(jsonDoc) + 1; std::unique_ptr jsonString(new char[jsonBufferLength]); - parsedJson.printTo(jsonString.get(), jsonBufferLength); - + serializeJson(jsonDoc, jsonString.get(), jsonBufferLength); return strdup(jsonString.get()); } @@ -262,7 +262,7 @@ HomieBootMode Config::getHomieBootModeOnNextBoot() { } } -void Config::write(const JsonObject& config) { +void Config::write(const JsonObject config) { if (!_spiffsBegin()) { return; } SPIFFS.remove(CONFIG_FILE_PATH); @@ -272,22 +272,21 @@ void Config::write(const JsonObject& config) { Interface::get().getLogger() << F("✖ Cannot open config file") << endl; return; } - - config.printTo(configFile); + serializeJson(config, configFile); configFile.close(); } bool Config::patch(const char* patch) { if (!_spiffsBegin()) { return false; } - StaticJsonBuffer patchJsonBuffer; - JsonObject& patchObject = patchJsonBuffer.parseObject(patch); + StaticJsonDocument patchJsonDoc; - if (!patchObject.success()) { + if (deserializeJson(patchJsonDoc, patch) != DeserializationError::Ok || !patchJsonDoc.is()) { Interface::get().getLogger() << F("✖ Invalid or too big JSON") << endl; return false; } + JsonObject patchObject = patchJsonDoc.as(); File configFile = SPIFFS.open(CONFIG_FILE_PATH, "r"); if (!configFile) { Interface::get().getLogger() << F("✖ Cannot open config file") << endl; @@ -301,27 +300,28 @@ bool Config::patch(const char* patch) { configFile.close(); configJson[configSize] = '\0'; - StaticJsonBuffer configJsonBuffer; - JsonObject& configObject = configJsonBuffer.parseObject(configJson); + StaticJsonDocument configJsonDoc; + deserializeJson(configJsonDoc, configJson); + JsonObject configObject = configJsonDoc.as(); // To do alow object that dont currently exist to be added like settings. // if settings wasnt there origionally then it should be allowed to be added by incremental. for (JsonObject::iterator it = patchObject.begin(); it != patchObject.end(); ++it) { - if (patchObject[it->key].is()) { - JsonObject& subObject = patchObject[it->key].as(); + if (patchObject[it->key()].is()) { + JsonObject subObject = patchObject[it->key()].as(); for (JsonObject::iterator it2 = subObject.begin(); it2 != subObject.end(); ++it2) { - if (!configObject.containsKey(it->key) || !configObject[it->key].is()) { + if (!configObject.containsKey(it->key()) || !configObject[it->key()].is()) { String error = "✖ Config does not contain a "; - error.concat(it->key); + error.concat(it->key().c_str()); error.concat(" object"); Interface::get().getLogger() << error << endl; return false; } - JsonObject& subConfigObject = configObject[it->key].as(); - subConfigObject[it2->key] = it2->value; + JsonObject subConfigObject = configObject[it->key()].as(); + subConfigObject[it2->key()] = it2->value(); } } else { - configObject[it->key] = it->value; + configObject[it->key()] = it->value(); } } diff --git a/src/Homie/Config.hpp b/src/Homie/Config.hpp index cc6f7d1c..6815e9eb 100644 --- a/src/Homie/Config.hpp +++ b/src/Homie/Config.hpp @@ -27,7 +27,7 @@ class Config { void erase(); void setHomieBootModeOnNextBoot(HomieBootMode bootMode); HomieBootMode getHomieBootModeOnNextBoot(); - void write(const JsonObject& config); + void write(const JsonObject config); bool patch(const char* patch); void log() const; // print the current config to log output bool isValid() const; diff --git a/src/Homie/Utils/Validation.cpp b/src/Homie/Utils/Validation.cpp index 39dafb27..0ea36573 100644 --- a/src/Homie/Utils/Validation.cpp +++ b/src/Homie/Utils/Validation.cpp @@ -2,7 +2,7 @@ using namespace HomieInternals; -ConfigValidationResult Validation::validateConfig(const JsonObject& object) { +ConfigValidationResult Validation::validateConfig(const JsonObject object) { ConfigValidationResult result; result = _validateConfigRoot(object); if (!result.valid) return result; @@ -19,7 +19,7 @@ ConfigValidationResult Validation::validateConfig(const JsonObject& object) { return result; } -ConfigValidationResult Validation::_validateConfigRoot(const JsonObject& object) { +ConfigValidationResult Validation::_validateConfigRoot(const JsonObject object) { ConfigValidationResult result; result.valid = false; if (!object.containsKey("name") || !object["name"].is()) { @@ -57,15 +57,15 @@ ConfigValidationResult Validation::_validateConfigRoot(const JsonObject& object) return result; } -ConfigValidationResult Validation::_validateConfigWifi(const JsonObject& object) { +ConfigValidationResult Validation::_validateConfigWifi(const JsonObject object) { ConfigValidationResult result; result.valid = false; - if (!object.containsKey("wifi") || !object["wifi"].is()) { + if (!object.containsKey("wifi") || !object["wifi"].is()) { result.reason = F("wifi is not an object"); return result; } - if (!object["wifi"].as().containsKey("ssid") || !object["wifi"]["ssid"].is()) { + if (!object["wifi"].as().containsKey("ssid") || !object["wifi"]["ssid"].is()) { result.reason = F("wifi.ssid is not a string"); return result; } @@ -73,7 +73,7 @@ ConfigValidationResult Validation::_validateConfigWifi(const JsonObject& object) result.reason = F("wifi.ssid is too long"); return result; } - if (!object["wifi"].as().containsKey("password") || !object["wifi"]["password"].is()) { + if (!object["wifi"].as().containsKey("password") || !object["wifi"]["password"].is()) { result.reason = F("wifi.password is not a string"); return result; } @@ -82,24 +82,24 @@ ConfigValidationResult Validation::_validateConfigWifi(const JsonObject& object) return result; } // by benzino - if (object["wifi"].as().containsKey("bssid") && !object["wifi"]["bssid"].is()) { + if (object["wifi"].as().containsKey("bssid") && !object["wifi"]["bssid"].is()) { result.reason = F("wifi.bssid is not a string"); return result; } - if ((object["wifi"].as().containsKey("bssid") && !object["wifi"].as().containsKey("channel")) || - (!object["wifi"].as().containsKey("bssid") && object["wifi"].as().containsKey("channel"))) { + if ((object["wifi"].as().containsKey("bssid") && !object["wifi"].as().containsKey("channel")) || + (!object["wifi"].as().containsKey("bssid") && object["wifi"].as().containsKey("channel"))) { result.reason = F("wifi.channel_bssid channel and BSSID is required"); return result; } - if (object["wifi"].as().containsKey("bssid") && !Helpers::validateMacAddress(object["wifi"].as().get("bssid"))) { + if (object["wifi"].as().containsKey("bssid") && !Helpers::validateMacAddress(object["wifi"].as().getMember("bssid").as())) { result.reason = F("wifi.bssid is not valid mac"); return result; } - if (object["wifi"].as().containsKey("channel") && !object["wifi"]["channel"].is()) { + if (object["wifi"].as().containsKey("channel") && !object["wifi"]["channel"].is()) { result.reason = F("wifi.channel is not an integer"); return result; } - if (object["wifi"].as().containsKey("ip") && !object["wifi"]["ip"].is()) { + if (object["wifi"].as().containsKey("ip") && !object["wifi"]["ip"].is()) { result.reason = F("wifi.ip is not a string"); return result; } @@ -107,11 +107,11 @@ ConfigValidationResult Validation::_validateConfigWifi(const JsonObject& object) result.reason = F("wifi.ip is too long"); return result; } - if (object["wifi"]["ip"] && !Helpers::validateIP(object["wifi"].as().get("ip"))) { + if (object["wifi"]["ip"] && !Helpers::validateIP(object["wifi"].as().getMember("ip").as())) { result.reason = F("wifi.ip is not valid ip address"); return result; } - if (object["wifi"].as().containsKey("mask") && !object["wifi"]["mask"].is()) { + if (object["wifi"].as().containsKey("mask") && !object["wifi"]["mask"].is()) { result.reason = F("wifi.mask is not a string"); return result; } @@ -119,11 +119,11 @@ ConfigValidationResult Validation::_validateConfigWifi(const JsonObject& object) result.reason = F("wifi.mask is too long"); return result; } - if (object["wifi"]["mask"] && !Helpers::validateIP(object["wifi"].as().get("mask"))) { + if (object["wifi"]["mask"] && !Helpers::validateIP(object["wifi"].as().getMember("mask").as())) { result.reason = F("wifi.mask is not valid mask"); return result; } - if (object["wifi"].as().containsKey("gw") && !object["wifi"]["gw"].is()) { + if (object["wifi"].as().containsKey("gw") && !object["wifi"]["gw"].is()) { result.reason = F("wifi.gw is not a string"); return result; } @@ -131,17 +131,17 @@ ConfigValidationResult Validation::_validateConfigWifi(const JsonObject& object) result.reason = F("wifi.gw is too long"); return result; } - if (object["wifi"]["gw"] && !Helpers::validateIP(object["wifi"].as().get("gw"))) { + if (object["wifi"]["gw"] && !Helpers::validateIP(object["wifi"].as().getMember("gw").as())) { result.reason = F("wifi.gw is not valid gateway address"); return result; } - if ((object["wifi"].as().containsKey("ip") && (!object["wifi"].as().containsKey("mask") || !object["wifi"].as().containsKey("gw"))) || - (object["wifi"].as().containsKey("gw") && (!object["wifi"].as().containsKey("mask") || !object["wifi"].as().containsKey("ip"))) || - (object["wifi"].as().containsKey("mask") && (!object["wifi"].as().containsKey("ip") || !object["wifi"].as().containsKey("gw")))) { + if ((object["wifi"].as().containsKey("ip") && (!object["wifi"].as().containsKey("mask") || !object["wifi"].as().containsKey("gw"))) || + (object["wifi"].as().containsKey("gw") && (!object["wifi"].as().containsKey("mask") || !object["wifi"].as().containsKey("ip"))) || + (object["wifi"].as().containsKey("mask") && (!object["wifi"].as().containsKey("ip") || !object["wifi"].as().containsKey("gw")))) { result.reason = F("wifi.staticip ip, gw and mask is required"); return result; } - if (object["wifi"].as().containsKey("dns1") && !object["wifi"]["dns1"].is()) { + if (object["wifi"].as().containsKey("dns1") && !object["wifi"]["dns1"].is()) { result.reason = F("wifi.dns1 is not a string"); return result; } @@ -149,15 +149,15 @@ ConfigValidationResult Validation::_validateConfigWifi(const JsonObject& object) result.reason = F("wifi.dns1 is too long"); return result; } - if (object["wifi"]["dns1"] && !Helpers::validateIP(object["wifi"].as().get("dns1"))) { + if (object["wifi"]["dns1"] && !Helpers::validateIP(object["wifi"].as().getMember("dns1").as())) { result.reason = F("wifi.dns1 is not valid dns address"); return result; } - if (object["wifi"].as().containsKey("dns2") && !object["wifi"].as().containsKey("dns1")) { + if (object["wifi"].as().containsKey("dns2") && !object["wifi"].as().containsKey("dns1")) { result.reason = F("wifi.dns2 no dns1 defined"); return result; } - if (object["wifi"].as().containsKey("dns2") && !object["wifi"]["dns2"].is()) { + if (object["wifi"].as().containsKey("dns2") && !object["wifi"]["dns2"].is()) { result.reason = F("wifi.dns2 is not a string"); return result; } @@ -165,7 +165,7 @@ ConfigValidationResult Validation::_validateConfigWifi(const JsonObject& object) result.reason = F("wifi.dns2 is too long"); return result; } - if (object["wifi"]["dns2"] && !Helpers::validateIP(object["wifi"].as().get("dns2"))) { + if (object["wifi"]["dns2"] && !Helpers::validateIP(object["wifi"].as().getMember("dns2").as())) { result.reason = F("wifi.dns2 is not valid dns address"); return result; } @@ -180,15 +180,15 @@ ConfigValidationResult Validation::_validateConfigWifi(const JsonObject& object) return result; } -ConfigValidationResult Validation::_validateConfigMqtt(const JsonObject& object) { +ConfigValidationResult Validation::_validateConfigMqtt(const JsonObject object) { ConfigValidationResult result; result.valid = false; - if (!object.containsKey("mqtt") || !object["mqtt"].is()) { + if (!object.containsKey("mqtt") || !object["mqtt"].is()) { result.reason = F("mqtt is not an object"); return result; } - if (!object["mqtt"].as().containsKey("host") || !object["mqtt"]["host"].is()) { + if (!object["mqtt"].as().containsKey("host") || !object["mqtt"]["host"].is()) { result.reason = F("mqtt.host is not a string"); return result; } @@ -196,17 +196,17 @@ ConfigValidationResult Validation::_validateConfigMqtt(const JsonObject& object) result.reason = F("mqtt.host is too long"); return result; } - if (object["mqtt"].as().containsKey("port") && !object["mqtt"]["port"].is()) { + if (object["mqtt"].as().containsKey("port") && !object["mqtt"]["port"].is()) { result.reason = F("mqtt.port is not an integer"); return result; } - if (object["mqtt"].as().containsKey("ssl")) { + if (object["mqtt"].as().containsKey("ssl")) { if (!object["mqtt"]["ssl"].is()) { result.reason = F("mqtt.ssl is not a bool"); return result; } } - if (object["mqtt"].as().containsKey("ssl_fingerprint")) { + if (object["mqtt"].as().containsKey("ssl_fingerprint")) { if (!object["mqtt"]["ssl_fingerprint"].is()) { result.reason = F("mqtt.ssl_fingerprint is not a string"); return result; @@ -217,7 +217,7 @@ ConfigValidationResult Validation::_validateConfigMqtt(const JsonObject& object) return result; } } - if (object["mqtt"].as().containsKey("base_topic")) { + if (object["mqtt"].as().containsKey("base_topic")) { if (!object["mqtt"]["base_topic"].is()) { result.reason = F("mqtt.base_topic is not a string"); return result; @@ -228,14 +228,14 @@ ConfigValidationResult Validation::_validateConfigMqtt(const JsonObject& object) return result; } } - if (object["mqtt"].as().containsKey("auth")) { + if (object["mqtt"].as().containsKey("auth")) { if (!object["mqtt"]["auth"].is()) { result.reason = F("mqtt.auth is not a boolean"); return result; } if (object["mqtt"]["auth"]) { - if (!object["mqtt"].as().containsKey("username") || !object["mqtt"]["username"].is()) { + if (!object["mqtt"].as().containsKey("username") || !object["mqtt"]["username"].is()) { result.reason = F("mqtt.username is not a string"); return result; } @@ -243,7 +243,7 @@ ConfigValidationResult Validation::_validateConfigMqtt(const JsonObject& object) result.reason = F("mqtt.username is too long"); return result; } - if (!object["mqtt"].as().containsKey("password") || !object["mqtt"]["password"].is()) { + if (!object["mqtt"].as().containsKey("password") || !object["mqtt"]["password"].is()) { result.reason = F("mqtt.password is not a string"); return result; } @@ -264,15 +264,15 @@ ConfigValidationResult Validation::_validateConfigMqtt(const JsonObject& object) return result; } -ConfigValidationResult Validation::_validateConfigOta(const JsonObject& object) { +ConfigValidationResult Validation::_validateConfigOta(const JsonObject object) { ConfigValidationResult result; result.valid = false; - if (!object.containsKey("ota") || !object["ota"].is()) { + if (!object.containsKey("ota") || !object["ota"].is()) { result.reason = F("ota is not an object"); return result; } - if (!object["ota"].as().containsKey("enabled") || !object["ota"]["enabled"].is()) { + if (!object["ota"].as().containsKey("enabled") || !object["ota"]["enabled"].is()) { result.reason = F("ota.enabled is not a boolean"); return result; } @@ -281,19 +281,19 @@ ConfigValidationResult Validation::_validateConfigOta(const JsonObject& object) return result; } -ConfigValidationResult Validation::_validateConfigSettings(const JsonObject& object) { +ConfigValidationResult Validation::_validateConfigSettings(const JsonObject object) { ConfigValidationResult result; result.valid = false; - StaticJsonBuffer<0> emptySettingsBuffer; + StaticJsonDocument<0> emptySettingsDoc; - JsonObject* settingsObject = &(emptySettingsBuffer.createObject()); + JsonObject settingsObject = emptySettingsDoc.to(); - if (object.containsKey("settings") && object["settings"].is()) { - settingsObject = &(object["settings"].as()); + if (object.containsKey("settings") && object["settings"].is()) { + settingsObject = object["settings"].as(); } - if (settingsObject->size() > MAX_CONFIG_SETTING_SIZE) {//max settings here and in isettings + if (settingsObject.size() > MAX_CONFIG_SETTING_SIZE) {//max settings here and in isettings result.reason = F("settings contains more elements than the set limit"); return result; } @@ -321,11 +321,11 @@ ConfigValidationResult Validation::_validateConfigSettings(const JsonObject& obj if (iSetting->isBool()) { HomieSetting* setting = static_cast*>(iSetting); - if (settingsObject->containsKey(setting->getName())) { - if (!(*settingsObject)[setting->getName()].is()) { + if (settingsObject.containsKey(setting->getName())) { + if (!settingsObject[setting->getName()].is()) { setReason(Issue::Type); return result; - } else if (!setting->validate((*settingsObject)[setting->getName()].as())) { + } else if (!setting->validate(settingsObject[setting->getName()].as())) { setReason(Issue::Validator); return result; } @@ -336,11 +336,11 @@ ConfigValidationResult Validation::_validateConfigSettings(const JsonObject& obj } else if (iSetting->isLong()) { HomieSetting* setting = static_cast*>(iSetting); - if (settingsObject->containsKey(setting->getName())) { - if (!(*settingsObject)[setting->getName()].is()) { + if (settingsObject.containsKey(setting->getName())) { + if (!settingsObject[setting->getName()].is()) { setReason(Issue::Type); return result; - } else if (!setting->validate((*settingsObject)[setting->getName()].as())) { + } else if (!setting->validate(settingsObject[setting->getName()].as())) { setReason(Issue::Validator); return result; } @@ -351,11 +351,11 @@ ConfigValidationResult Validation::_validateConfigSettings(const JsonObject& obj } else if (iSetting->isDouble()) { HomieSetting* setting = static_cast*>(iSetting); - if (settingsObject->containsKey(setting->getName())) { - if (!(*settingsObject)[setting->getName()].is()) { + if (settingsObject.containsKey(setting->getName())) { + if (!settingsObject[setting->getName()].is()) { setReason(Issue::Type); return result; - } else if (!setting->validate((*settingsObject)[setting->getName()].as())) { + } else if (!setting->validate(settingsObject[setting->getName()].as())) { setReason(Issue::Validator); return result; } @@ -366,11 +366,11 @@ ConfigValidationResult Validation::_validateConfigSettings(const JsonObject& obj } else if (iSetting->isConstChar()) { HomieSetting* setting = static_cast*>(iSetting); - if (settingsObject->containsKey(setting->getName())) { - if (!(*settingsObject)[setting->getName()].is()) { + if (settingsObject.containsKey(setting->getName())) { + if (!settingsObject[setting->getName()].is()) { setReason(Issue::Type); return result; - } else if (!setting->validate((*settingsObject)[setting->getName()].as())) { + } else if (!setting->validate(settingsObject[setting->getName()].as())) { setReason(Issue::Validator); return result; } diff --git a/src/Homie/Utils/Validation.hpp b/src/Homie/Utils/Validation.hpp index efa39fc7..a8babbb8 100644 --- a/src/Homie/Utils/Validation.hpp +++ b/src/Homie/Utils/Validation.hpp @@ -15,13 +15,13 @@ struct ConfigValidationResult { class Validation { public: - static ConfigValidationResult validateConfig(const JsonObject& object); + static ConfigValidationResult validateConfig(const JsonObject object); private: - static ConfigValidationResult _validateConfigRoot(const JsonObject& object); - static ConfigValidationResult _validateConfigWifi(const JsonObject& object); - static ConfigValidationResult _validateConfigMqtt(const JsonObject& object); - static ConfigValidationResult _validateConfigOta(const JsonObject& object); - static ConfigValidationResult _validateConfigSettings(const JsonObject& object); + static ConfigValidationResult _validateConfigRoot(const JsonObject object); + static ConfigValidationResult _validateConfigWifi(const JsonObject object); + static ConfigValidationResult _validateConfigMqtt(const JsonObject object); + static ConfigValidationResult _validateConfigOta(const JsonObject object); + static ConfigValidationResult _validateConfigSettings(const JsonObject object); }; } // namespace HomieInternals