Supports ArduinoJson V6. Issue #47

pull/57/head
Hieromon Ikasamo 6 years ago
parent 2c0207fb40
commit e790a0f4ac
  1. 8
      examples/FileUpload/FileUpload.ino
  2. 2
      examples/Simple/Simple.ino
  3. 30
      examples/mqttRSSI/mqttRSSI.ino
  4. 9
      examples/mqttRSSI_FS/mqttRSSI_FS.ino
  5. 4
      src/AutoConnect.h
  6. 467
      src/AutoConnectAux.cpp
  7. 4
      src/AutoConnectAux.h
  8. 416
      src/AutoConnectAuxImpl.h
  9. 12
      src/AutoConnectDefs.h
  10. 66
      src/AutoConnectElementBasis.h
  11. 60
      src/AutoConnectElementBasisImpl.h
  12. 110
      src/AutoConnectElementJson.h
  13. 133
      src/AutoConnectElementJsonImpl.h

@ -115,10 +115,10 @@ String postUpload(AutoConnectAux& aux, PageArgument& args) {
String content; String content;
// Explicitly cast to the desired element to correctly extract // Explicitly cast to the desired element to correctly extract
// the element using the operator []. // the element using the operator [].
AutoConnectFile& filename = (AutoConnectFile&)auxUpload["filename"]; AutoConnectFile& filename = auxUpload["filename"].as<AutoConnectFile>();
AutoConnectText& aux_filename = (AutoConnectText&)aux["filename"]; AutoConnectText& aux_filename = aux["filename"].as<AutoConnectText>();
AutoConnectText& aux_size = (AutoConnectText&)aux["size"]; AutoConnectText& aux_size = aux["size"].as<AutoConnectText>();
AutoConnectText& aux_contentType = (AutoConnectText&)aux["content_type"]; AutoConnectText& aux_contentType = aux["content_type"].as<AutoConnectText>();
// Assignment operator can be used for the element attribute. // Assignment operator can be used for the element attribute.
aux_filename.value = filename.value; aux_filename.value = filename.value;
aux_size.value = String(filename.size); aux_size.value = String(filename.size);

@ -158,7 +158,7 @@ void setup() {
Timezone.load(AUX_TIMEZONE); Timezone.load(AUX_TIMEZONE);
// Retrieve the select element that holds the time zone code and // Retrieve the select element that holds the time zone code and
// register the zone mnemonic in advance. // register the zone mnemonic in advance.
AutoConnectSelect& tz = Timezone.getElement<AutoConnectSelect>("timezone"); AutoConnectSelect& tz = Timezone["timezone"].as<AutoConnectSelect>();
for (uint8_t n = 0; n < sizeof(TZ) / sizeof(Timezone_t); n++) { for (uint8_t n = 0; n < sizeof(TZ) / sizeof(Timezone_t); n++) {
tz.add(String(TZ[n].zone)); tz.add(String(TZ[n].zone));
} }

@ -256,42 +256,38 @@ String loadParams(AutoConnectAux& aux, PageArgument& args) {
String saveParams(AutoConnectAux& aux, PageArgument& args) { String saveParams(AutoConnectAux& aux, PageArgument& args) {
// The 'where()' function returns the AutoConnectAux that caused // The 'where()' function returns the AutoConnectAux that caused
// the transition to this page. // the transition to this page.
AutoConnectAux* mqtt_setting = portal.where(); AutoConnectAux& mqtt_setting = portal.where();
AutoConnectInput& mqttserver = mqtt_setting->getElement<AutoConnectInput>("mqttserver"); AutoConnectInput& mqttserver = mqtt_setting["mqttserver"].as<AutoConnectInput>();
serverName = mqttserver.value; serverName = mqttserver.value;
serverName.trim(); serverName.trim();
AutoConnectInput& channelid = mqtt_setting->getElement<AutoConnectInput>("channelid"); channelId = mqtt_setting["channelid"].value;
channelId = channelid.value;
channelId.trim(); channelId.trim();
AutoConnectInput& userkey = mqtt_setting->getElement<AutoConnectInput>("userkey"); userKey = mqtt_setting["userkey"].value;
userKey = userkey.value;
userKey.trim(); userKey.trim();
AutoConnectInput& apikey = mqtt_setting->getElement<AutoConnectInput>("apikey"); apiKey = mqtt_setting["apikey"].value;
apiKey = apikey.value;
apiKey.trim(); apiKey.trim();
AutoConnectRadio& period = mqtt_setting->getElement<AutoConnectRadio>("period"); AutoConnectRadio& period = mqtt_setting["period"].as<AutoConnectRadio>();
updateInterval = period.value().substring(0, 2).toInt() * 1000; updateInterval = period.value().substring(0, 2).toInt() * 1000;
bool uniqueid = mqtt_setting->getElement<AutoConnectCheckbox>("uniqueid").checked; bool uniqueid = mqtt_setting["uniqueid"].as<AutoConnectCheckbox>().checked;
AutoConnectInput& hostname = mqtt_setting->getElement<AutoConnectInput>("hostname"); hostName = mqtt_setting["hostname"].value;
hostName = hostname.value;
hostName.trim(); hostName.trim();
// The entered value is owned by AutoConnectAux of /mqtt_setting. // The entered value is owned by AutoConnectAux of /mqtt_setting.
// To retrieve the elements of /mqtt_setting, it is necessary to get // To retrieve the elements of /mqtt_setting, it is necessary to get
// the AutoConnectAux object of /mqtt_setting. // the AutoConnectAux object of /mqtt_setting.
File param = SPIFFS.open(PARAM_FILE, "w"); File param = SPIFFS.open(PARAM_FILE, "w");
mqtt_setting->saveElement(param, { "mqttserver", "channelid", "userkey", "apikey", "uniqueid", "hostname" }); mqtt_setting.saveElement(param, { "mqttserver", "channelid", "userkey", "apikey", "uniqueid", "hostname" });
param.close(); param.close();
// Echo back saved parameters to AutoConnectAux page. // Echo back saved parameters to AutoConnectAux page.
AutoConnectText& echo = aux.getElement<AutoConnectText>("parameters"); AutoConnectText& echo = aux["parameters"].as<AutoConnectText>();
echo.value = "Server: " + serverName; echo.value = "Server: " + serverName;
echo.value += mqttserver.isValid() ? String(" (OK)") : String(" (ERR)"); echo.value += mqttserver.isValid() ? String(" (OK)") : String(" (ERR)");
echo.value += "<br>Channel ID: " + channelId + "<br>"; echo.value += "<br>Channel ID: " + channelId + "<br>";
@ -354,9 +350,9 @@ void setup() {
SPIFFS.begin(); SPIFFS.begin();
if (portal.load(FPSTR(AUX_mqtt_setting))) { if (portal.load(FPSTR(AUX_mqtt_setting))) {
AutoConnectAux* mqtt_setting = portal.aux(AUX_SETTING_URI); AutoConnectAux& mqtt_setting = *portal.aux(AUX_SETTING_URI);
AutoConnectCheckbox& uniqueidElm = mqtt_setting->getElement<AutoConnectCheckbox>("uniqueid"); AutoConnectCheckbox& uniqueidElm = mqtt_setting["uniqueid"].as<AutoConnectCheckbox>();
AutoConnectInput& hostnameElm = mqtt_setting->getElement<AutoConnectInput>("hostname"); AutoConnectInput& hostnameElm = mqtt_setting["hostname"].as<AutoConnectInput>();
if (uniqueidElm.checked) { if (uniqueidElm.checked) {
config.apid = String("ESP") + "-" + String(GET_CHIPID(), HEX); config.apid = String("ESP") + "-" + String(GET_CHIPID(), HEX);
Serial.println("apid set to " + config.apid); Serial.println("apid set to " + config.apid);

@ -149,7 +149,7 @@ String saveParams(AutoConnectAux& aux, PageArgument& args) {
param.close(); param.close();
// Echo back saved parameters to AutoConnectAux page. // Echo back saved parameters to AutoConnectAux page.
AutoConnectText& echo = aux.getElement<AutoConnectText>("parameters"); AutoConnectText& echo = aux["parameters"].as<AutoConnectText>();
echo.value = "Server: " + serverName + "<br>"; echo.value = "Server: " + serverName + "<br>";
echo.value += "Channel ID: " + channelId + "<br>"; echo.value += "Channel ID: " + channelId + "<br>";
echo.value += "User Key: " + userKey + "<br>"; echo.value += "User Key: " + userKey + "<br>";
@ -231,9 +231,10 @@ void setup() {
AutoConnectAux* setting = portal.aux(AUX_MQTTSETTING); AutoConnectAux* setting = portal.aux(AUX_MQTTSETTING);
if (setting) { if (setting) {
PageArgument args; PageArgument args;
loadParams(*setting, args); AutoConnectAux& mqtt_setting = *setting;
AutoConnectCheckbox& uniqueidElm = setting->getElement<AutoConnectCheckbox>("uniqueid"); loadParams(mqtt_setting, args);
AutoConnectInput& hostnameElm = setting->getElement<AutoConnectInput>("hostname"); AutoConnectCheckbox& uniqueidElm = mqtt_setting["uniqueid"].as<AutoConnectCheckbox>();
AutoConnectInput& hostnameElm = mqtt_setting["hostname"].as<AutoConnectInput>();
if (uniqueidElm.checked) { if (uniqueidElm.checked) {
config.apid = String("ESP") + "-" + String(GET_CHIPID(), HEX); config.apid = String("ESP") + "-" + String(GET_CHIPID(), HEX);
Serial.println("apid set to " + config.apid); Serial.println("apid set to " + config.apid);

@ -185,7 +185,7 @@ class AutoConnect {
void join(AutoConnectAux& aux); void join(AutoConnectAux& aux);
void join(AutoConnectAuxVT auxVector); void join(AutoConnectAuxVT auxVector);
bool on(const String& uri, const AuxHandlerFunctionT handler, AutoConnectExitOrder_t order = AC_EXIT_AHEAD); bool on(const String& uri, const AuxHandlerFunctionT handler, AutoConnectExitOrder_t order = AC_EXIT_AHEAD);
AutoConnectAux* where(void) const { return aux(_auxUri); } AutoConnectAux& where(void) const { return *aux(_auxUri); }
/** For AutoConnectAux described in JSON */ /** For AutoConnectAux described in JSON */
#ifdef AUTOCONNECT_USE_JSON #ifdef AUTOCONNECT_USE_JSON
@ -220,6 +220,8 @@ class AutoConnect {
void _purgePages(void); void _purgePages(void);
virtual PageElement* _setupPage(String uri); virtual PageElement* _setupPage(String uri);
#ifdef AUTOCONNECT_USE_JSON #ifdef AUTOCONNECT_USE_JSON
template<typename T>
bool _parseJson(T in);
bool _load(JsonVariant& aux); bool _load(JsonVariant& aux);
#endif // !AUTOCONNECT_USE_JSON #endif // !AUTOCONNECT_USE_JSON

@ -9,8 +9,8 @@
#include <algorithm> #include <algorithm>
#include "AutoConnect.h" #include "AutoConnect.h"
#include "AutoConnectAux.h" #include "AutoConnectAux.h"
#include "AutoConnectAuxImpl.h"
#include "AutoConnectUploadImpl.h" #include "AutoConnectUploadImpl.h"
#include "AutoConnectElement.h"
#include "AutoConnectElementBasisImpl.h" #include "AutoConnectElementBasisImpl.h"
#ifdef AUTOCONNECT_USE_JSON #ifdef AUTOCONNECT_USE_JSON
#include "AutoConnectElementJsonImpl.h" #include "AutoConnectElementJsonImpl.h"
@ -466,309 +466,7 @@ void AutoConnectAux::_storeElements(WebServerClass* webServer) {
} }
} }
#ifndef AUTOCONNECT_USE_JSON #ifdef AUTOCONNECT_USE_JSON
/**
* Get AutoConnectElementBasis element.
* @param name an element name.
* @return A reference of AutoConnectElement class.
*/
template<>
AutoConnectElementBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
return *(reinterpret_cast<AutoConnectElementBasis*>(elm));
}
return reinterpret_cast<AutoConnectElementBasis&>(_nullElement());
}
/**
* Get AutoConnectButtonBasis element.
* @param name An element name.
* @return A reference of AutoConnectButton class.
*/
template<>
AutoConnectButtonBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Button)
return *(reinterpret_cast<AutoConnectButtonBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectButtonBasis&>(_nullElement());
}
/**
* Get AutoConnectCheckboxBasis element.
* @param name An element name.
* @return A reference of AutoConnectCheckbox class.
*/
template<>
AutoConnectCheckboxBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Checkbox)
return *(reinterpret_cast<AutoConnectCheckboxBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectCheckboxBasis&>(_nullElement());
}
/**
* Get AutoConnectFileBasis element.
* @param name An element name.
* @return A reference of AutoConnectFile class.
*/
template<>
AutoConnectFileBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_File)
return *(reinterpret_cast<AutoConnectFileBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectFileBasis&>(_nullElement());
}
/**
* Get AutoConnectInputBasis element.
* @param name An element name.
* @return A reference of AutoConnectInput class.
*/
template<>
AutoConnectInputBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Input)
return *(reinterpret_cast<AutoConnectInputBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectInputBasis&>(_nullElement());
}
/**
* Get AutoConnectRadioBasis element.
* @param name An element name.
* @return A reference of AutoConnectRadio class.
*/
template<>
AutoConnectRadioBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Radio)
return *(reinterpret_cast<AutoConnectRadioBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectRadioBasis&>(_nullElement());
}
/**
* Get AutoConnectSelectBasis element.
* @param name An element name.
* @return A reference of AutoConnectSelect class.
*/
template<>
AutoConnectSelectBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Select)
return *(reinterpret_cast<AutoConnectSelectBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectSelectBasis&>(_nullElement());
}
/**
* Get AutoConnectSubmitBasis element.
* @param name An element name.
* @return A reference of AutoConnectSubmit class.
*/
template<>
AutoConnectSubmitBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Submit)
return *(reinterpret_cast<AutoConnectSubmitBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectSubmitBasis&>(_nullElement());
}
/**
* Get AutoConnectTextBasis element.
* @param name An element name.
* @return A reference of AutoConnectText class.
*/
template<>
AutoConnectTextBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Text)
return *(reinterpret_cast<AutoConnectTextBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectTextBasis&>(_nullElement());
}
#else
/**
* Get AutoConnectElementJson element.
* @param name an element name.
* @return A reference of AutoConnectElement class.
*/
template<>
AutoConnectElementJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
return *(reinterpret_cast<AutoConnectElementJson*>(elm));
}
return reinterpret_cast<AutoConnectElementJson&>(_nullElement());
}
/**
* Get AutoConnectButtonJson element.
* @param name An element name.
* @return A reference of AutoConnectButton class.
*/
template<>
AutoConnectButtonJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Button)
return *(reinterpret_cast<AutoConnectButtonJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectButtonJson&>(_nullElement());
}
/**
* Get AutoConnectCheckboxJson element.
* @param name An element name.
* @return A reference of AutoConnectCheckbox class.
*/
template<>
AutoConnectCheckboxJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Checkbox)
return *(reinterpret_cast<AutoConnectCheckboxJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectCheckboxJson&>(_nullElement());
}
/**
* Get AutoConnectFile element.
* @param name An element name.
* @return A reference of AutoConnectFile class.
*/
template<>
AutoConnectFileJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_File)
return *(reinterpret_cast<AutoConnectFileJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectFileJson&>(_nullElement());
}
/**
* Get AutoConnectInputJson element.
* @param name An element name.
* @return A reference of AutoConnectInput class.
*/
template<>
AutoConnectInputJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Input)
return *(reinterpret_cast<AutoConnectInputJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectInputJson&>(_nullElement());
}
/**
* Get AutoConnectRadioJson element.
* @param name An element name.
* @return A reference of AutoConnectRadio class.
*/
template<>
AutoConnectRadioJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Radio)
return *(reinterpret_cast<AutoConnectRadioJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectRadioJson&>(_nullElement());
}
/**
* Get AutoConnectSelectJson element.
* @param name An element name.
* @return A reference of AutoConnectSelect class.
*/
template<>
AutoConnectSelectJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Select)
return *(reinterpret_cast<AutoConnectSelectJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectSelectJson&>(_nullElement());
}
/**
* Get AutoConnectSubmitJson element.
* @param name An element name.
* @return A reference of AutoConnectSubmit class.
*/
template<>
AutoConnectSubmitJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Submit)
return *(reinterpret_cast<AutoConnectSubmitJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectSubmitJson&>(_nullElement());
}
/**
* Get AutoConnectTextJson element.
* @param name An element name.
* @return A reference of AutoConnectText class.
*/
template<>
AutoConnectTextJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Text)
return *(reinterpret_cast<AutoConnectTextJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectTextJson&>(_nullElement());
}
/** /**
* Load AutoConnectAux page from JSON description stored in the sketch. * Load AutoConnectAux page from JSON description stored in the sketch.
@ -778,35 +476,29 @@ AutoConnectTextJson& AutoConnectAux::getElement(const String& name) {
* @return true Successfully loaded. * @return true Successfully loaded.
*/ */
bool AutoConnect::load(const String& aux) { bool AutoConnect::load(const String& aux) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE); return _parseJson<const String&>(aux);
JsonVariant jv = jsonBuffer.parse(aux);
return _load(jv);
} }
/** /**
* Load AutoConnectAux page from JSON description stored in PROGMEM. * Load AutoConnectAux page from JSON description stored in PROGMEM.
* This function can load AutoConnectAux for multiple AUX pages written * This function can load AutoConnectAux for multiple AUX pages written
* in JSON and is registered in AutoConnect. * in JSON and is registered in AutoConnect.
* @param aux JSON description to be load. * @param aux JSON description to be load.
* @return true Successfully loaded. * @return true Successfully loaded.
*/ */
bool AutoConnect::load(const __FlashStringHelper* aux) { bool AutoConnect::load(const __FlashStringHelper* aux) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE); return _parseJson<const __FlashStringHelper*>(aux);
JsonVariant jv = jsonBuffer.parse(aux);
return _load(jv);
} }
/** /**
* Load AutoConnectAux page from JSON description from the stream. * Load AutoConnectAux page from JSON description from the stream.
* This function can load AutoConnectAux for multiple AUX pages written * This function can load AutoConnectAux for multiple AUX pages written
* in JSON and is registered in AutoConnect. * in JSON and is registered in AutoConnect.
* @param aux Stream for read AutoConnectAux elements. * @param aux Stream for read AutoConnectAux elements.
* @return true Successfully loaded. * @return true Successfully loaded.
*/ */
bool AutoConnect::load(Stream& aux) { bool AutoConnect::load(Stream& aux) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE); return _parseJson<Stream&>(aux);
JsonVariant jv = jsonBuffer.parse(aux);
return _load(jv);
} }
/** /**
@ -815,34 +507,29 @@ bool AutoConnect::load(Stream& aux) {
* @return true Successfully loaded. * @return true Successfully loaded.
*/ */
bool AutoConnect::_load(JsonVariant& auxJson) { bool AutoConnect::_load(JsonVariant& auxJson) {
bool rc = auxJson.success(); bool rc = true;
if (rc) { if (auxJson.is<JsonArray>()) {
if (auxJson.is<JsonArray>()) { ArduinoJsonArray jb = auxJson.as<JsonArray>();
JsonArray& jb = auxJson.as<JsonArray>(); for (ArduinoJsonObject auxJson : jb) {
for (JsonObject& auxJson : jb) {
AutoConnectAux* newAux = new AutoConnectAux;
if (newAux->_load(auxJson))
join(*newAux);
else {
delete newAux;
rc = false;
break;
}
}
}
else {
JsonObject& jb = auxJson.as<JsonObject>();
AutoConnectAux* newAux = new AutoConnectAux; AutoConnectAux* newAux = new AutoConnectAux;
if (newAux->_load(jb)) if (newAux->_load(auxJson))
join(*newAux); join(*newAux);
else { else {
delete newAux; delete newAux;
rc = false; rc = false;
break;
} }
} }
} }
else { else {
AC_DBG("JSON parse error\n"); ArduinoJsonObject jb = auxJson.as<JsonObject>();
AutoConnectAux* newAux = new AutoConnectAux;
if (newAux->_load(jb))
join(*newAux);
else {
delete newAux;
rc = false;
}
} }
return rc; return rc;
} }
@ -854,7 +541,7 @@ bool AutoConnect::_load(JsonVariant& auxJson) {
*/ */
AutoConnectElement* AutoConnectAux::_createElement(const JsonObject& json) { AutoConnectElement* AutoConnectAux::_createElement(const JsonObject& json) {
AutoConnectElement* elm = nullptr; AutoConnectElement* elm = nullptr;
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE)); String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
switch (_asElementType(type)) { switch (_asElementType(type)) {
case AC_Element: case AC_Element:
@ -906,9 +593,7 @@ AutoConnectElement* AutoConnectAux::_createElement(const JsonObject& json) {
* @return false Invalid JSON data occurred. * @return false Invalid JSON data occurred.
*/ */
bool AutoConnectAux::load(const String& in) { bool AutoConnectAux::load(const String& in) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE); return _parseJson<const String&>(in);
JsonObject& jb = jsonBuffer.parseObject(in);
return _load(jb);
} }
/** /**
@ -920,9 +605,7 @@ bool AutoConnectAux::load(const String& in) {
* @return false Invalid JSON data occurred. * @return false Invalid JSON data occurred.
*/ */
bool AutoConnectAux::load(const __FlashStringHelper* in) { bool AutoConnectAux::load(const __FlashStringHelper* in) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE); return _parseJson<const __FlashStringHelper*>(in);
JsonObject& jb = jsonBuffer.parseObject(in);
return _load(jb);
} }
/** /**
@ -934,9 +617,7 @@ bool AutoConnectAux::load(const __FlashStringHelper* in) {
* @return false Invalid JSON data occurred. * @return false Invalid JSON data occurred.
*/ */
bool AutoConnectAux::load(Stream& in) { bool AutoConnectAux::load(Stream& in) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE); return _parseJson<Stream&>(in);
JsonObject& jb = jsonBuffer.parseObject(in);
return _load(jb);
} }
/** /**
@ -946,15 +627,10 @@ bool AutoConnectAux::load(Stream& in) {
* @return false loading unsuccessful, JSON parsing error occurred. * @return false loading unsuccessful, JSON parsing error occurred.
*/ */
bool AutoConnectAux::_load(JsonObject& jb) { bool AutoConnectAux::_load(JsonObject& jb) {
if (!jb.success()) { _title = jb[F(AUTOCONNECT_JSON_KEY_TITLE)].as<String>();
AC_DBG("json parse error\n"); _uriStr = jb[F(AUTOCONNECT_JSON_KEY_URI)].as<String>();
return false;
}
_title = jb.get<String>(F(AUTOCONNECT_JSON_KEY_TITLE));
_uriStr = jb.get<String>(F(AUTOCONNECT_JSON_KEY_URI));
_uri = _uriStr.c_str(); _uri = _uriStr.c_str();
_menu = jb.get<bool>(F(AUTOCONNECT_JSON_KEY_MENU)); _menu = jb[F(AUTOCONNECT_JSON_KEY_MENU)].as<bool>();
JsonVariant elements = jb[F(AUTOCONNECT_JSON_KEY_ELEMENT)]; JsonVariant elements = jb[F(AUTOCONNECT_JSON_KEY_ELEMENT)];
(void)_loadElement(elements, ""); (void)_loadElement(elements, "");
return true; return true;
@ -971,49 +647,41 @@ bool AutoConnectAux::_load(JsonObject& jb) {
* @return A reference of loaded AutoConnectElement instance. * @return A reference of loaded AutoConnectElement instance.
*/ */
bool AutoConnectAux::loadElement(const String& in, const String& name) { bool AutoConnectAux::loadElement(const String& in, const String& name) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE); return _parseElement<const String&>(in, name);
JsonVariant jb = jsonBuffer.parse(in);
return _loadElement(jb, name);
} }
bool AutoConnectAux::loadElement(const __FlashStringHelper* in, const String& name) { bool AutoConnectAux::loadElement(const __FlashStringHelper* in, const String& name) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE); return _parseElement<const __FlashStringHelper*>(in, name);
JsonVariant jb = jsonBuffer.parse(in);
return _loadElement(jb, name);
} }
bool AutoConnectAux::loadElement(Stream& in, const String& name) { bool AutoConnectAux::loadElement(Stream& in, const String& name) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE); return _parseElement<Stream&>(in, name);
JsonVariant jb = jsonBuffer.parse(in);
return _loadElement(jb, name);
} }
bool AutoConnectAux::_loadElement(JsonVariant& jb, const String& name) { bool AutoConnectAux::_loadElement(JsonVariant& jb, const String& name) {
bool rc = jb.success(); bool rc = true;
if (rc) { if (jb.is<JsonArray>()) {
if (jb.is<JsonArray>()) { ArduinoJsonArray elements = jb.as<JsonArray>();
JsonArray& elements = jb.as<JsonArray>(); for (ArduinoJsonObject element : elements) {
for (JsonObject& element : elements) {
AutoConnectElement& elm = _loadElement(element, name);
if (!elm.name.length()) {
rc = false;
break;
}
}
}
else {
JsonObject& element = jb.as<JsonObject>();
AutoConnectElement& elm = _loadElement(element, name); AutoConnectElement& elm = _loadElement(element, name);
if (!elm.name.length()) if (!elm.name.length()) {
rc = false; rc = false;
break;
}
} }
} }
else {
ArduinoJsonObject element = jb.as<JsonObject>();
AutoConnectElement& elm = _loadElement(element, name);
if (!elm.name.length())
rc = false;
}
return rc; return rc;
} }
AutoConnectElement& AutoConnectAux::_loadElement(JsonObject& element, const String& name) { AutoConnectElement& AutoConnectAux::_loadElement(JsonObject& element, const String& name) {
AutoConnectElement* auxElm = nullptr; AutoConnectElement* auxElm = nullptr;
String elmName = element.get<String>(F(AUTOCONNECT_JSON_KEY_NAME)); String elmName = element[F(AUTOCONNECT_JSON_KEY_NAME)].as<String>();
if (!name.length() || name.equalsIgnoreCase(elmName)) { if (!name.length() || name.equalsIgnoreCase(elmName)) {
// The specified element is defined in the JSON stream. // The specified element is defined in the JSON stream.
// Loads from JSON object. // Loads from JSON object.
@ -1067,40 +735,43 @@ size_t AutoConnectAux::saveElement(Stream& out, std::vector<String> const& names
bufferSize += elm.getObjectSize(); bufferSize += elm.getObjectSize();
break; break;
} }
// Round up to 16 boundary
bufferSize = bufferSize > 0 ? ((bufferSize + 16) & (~0xf)) : bufferSize;
// Serialization
if (bufferSize > 0) { if (bufferSize > 0) {
DynamicJsonBuffer jb(bufferSize); ArduinoJsonBuffer jb(bufferSize);
if (amount == 1) { if (amount == 1) {
JsonObject& element = jb.createObject(); ArduinoJsonObject element = ARDUINOJSON_CREATEOBJECT(jb);
for (AutoConnectElement& elm : _addonElm) for (AutoConnectElement& elm : _addonElm)
if (elm.name.equalsIgnoreCase(names[0])) { if (elm.name.equalsIgnoreCase(names[0])) {
elm.serialize(element); elm.serialize(element);
break; break;
} }
size_n = element.printTo(out); size_n = ARDUINOJSON_PRINT(element, out);
} }
else if (amount == 0) { else if (amount == 0) {
JsonObject& json = jb.createObject(); ArduinoJsonObject json = ARDUINOJSON_CREATEOBJECT(jb);
json[F(AUTOCONNECT_JSON_KEY_TITLE)] = _title; json[F(AUTOCONNECT_JSON_KEY_TITLE)] = _title;
json[F(AUTOCONNECT_JSON_KEY_URI)] = _uriStr; json[F(AUTOCONNECT_JSON_KEY_URI)] = _uriStr;
json[F(AUTOCONNECT_JSON_KEY_MENU)] = _menu; json[F(AUTOCONNECT_JSON_KEY_MENU)] = _menu;
JsonArray& elements = json.createNestedArray(F(AUTOCONNECT_JSON_KEY_ELEMENT)); ArduinoJsonArray elements = json.createNestedArray(F(AUTOCONNECT_JSON_KEY_ELEMENT));
for (AutoConnectElement& elm : _addonElm) { for (AutoConnectElement& elm : _addonElm) {
JsonObject& element = elements.createNestedObject(); ArduinoJsonObject element = elements.createNestedObject();
elm.serialize(element); elm.serialize(element);
} }
size_n = json.prettyPrintTo(out); size_n = ARDUINOJSON_PRETTYPRINT(json, out);
} }
else if (amount >= 2) { else if (amount >= 2) {
JsonArray& elements = jb.createArray(); ArduinoJsonArray elements = ARDUINOJSON_CREATEARRAY(jb);
for (String name : names) for (String name : names)
for (AutoConnectElement& elm : _addonElm) for (AutoConnectElement& elm : _addonElm)
if (elm.name.equalsIgnoreCase(name)) { if (elm.name.equalsIgnoreCase(name)) {
JsonObject& element = elements.createNestedObject(); ArduinoJsonObject element = elements.createNestedObject();
elm.serialize(element); elm.serialize(element);
break; break;
} }
size_n = elements.prettyPrintTo(out); size_n = ARDUINOJSON_PRETTYPRINT(elements, out);
} }
} }
return size_n; return size_n;
@ -1136,4 +807,4 @@ ACElement_t AutoConnectAux::_asElementType(const String& type) {
return t; return t;
} }
#endif // AUTOCONNECT_USE_JSON #endif // !AUTOCONNECT_USE_JSON

@ -88,8 +88,12 @@ class AutoConnectAux : public PageBuilder {
static AutoConnectElement& _nullElement(void); /**< A static returning value as invalid */ static AutoConnectElement& _nullElement(void); /**< A static returning value as invalid */
#ifdef AUTOCONNECT_USE_JSON #ifdef AUTOCONNECT_USE_JSON
template<typename T>
bool _parseJson(T in);
bool _load(JsonObject& in); /**< Load all elements from JSON object */ bool _load(JsonObject& in); /**< Load all elements from JSON object */
bool _loadElement(JsonVariant& in, const String& name); /**< Load an element as specified name from JSON object */ bool _loadElement(JsonVariant& in, const String& name); /**< Load an element as specified name from JSON object */
template<typename T>
bool _parseElement(T in, const String& name);
AutoConnectElement& _loadElement(JsonObject& in, const String& name); /**< Load an element as specified name from JSON object */ AutoConnectElement& _loadElement(JsonObject& in, const String& name); /**< Load an element as specified name from JSON object */
AutoConnectElement* _createElement(const JsonObject& json); /**< Create an AutoConnectElement instance from JSON object */ AutoConnectElement* _createElement(const JsonObject& json); /**< Create an AutoConnectElement instance from JSON object */
static ACElement_t _asElementType(const String& type); /**< Convert a string of element type to the enumeration value */ static ACElement_t _asElementType(const String& type); /**< Convert a string of element type to the enumeration value */

@ -0,0 +1,416 @@
/**
* Implementation of template functions of AutoConnect and AutoConnectAux.
* This implementation instantiates completely the void AutoConnectElement
* as each type and also absorbs interface differences due to ArduinoJson
* version differences.
* @file AutoConnectAuxImpl.h
* @author hieromon@gmail.com
* @version 0.9.8
* @date 2019-03-21
* @copyright MIT license.
*/
#ifndef _AUTOCONNECTAUXIMPL_H_
#define _AUTOCONNECTAUXIMPL_H_
#include "AutoConnectDefs.h"
#ifndef AUTOCONNECT_USE_JSON
/**
* Get AutoConnectElementBasis element.
* @param name an element name.
* @return A reference of AutoConnectElement class.
*/
template<>
AutoConnectElementBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
return *(reinterpret_cast<AutoConnectElementBasis*>(elm));
}
return reinterpret_cast<AutoConnectElementBasis&>(_nullElement());
}
/**
* Get AutoConnectButtonBasis element.
* @param name An element name.
* @return A reference of AutoConnectButton class.
*/
template<>
AutoConnectButtonBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Button)
return *(reinterpret_cast<AutoConnectButtonBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectButtonBasis&>(_nullElement());
}
/**
* Get AutoConnectCheckboxBasis element.
* @param name An element name.
* @return A reference of AutoConnectCheckbox class.
*/
template<>
AutoConnectCheckboxBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Checkbox)
return *(reinterpret_cast<AutoConnectCheckboxBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectCheckboxBasis&>(_nullElement());
}
/**
* Get AutoConnectFileBasis element.
* @param name An element name.
* @return A reference of AutoConnectFile class.
*/
template<>
AutoConnectFileBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_File)
return *(reinterpret_cast<AutoConnectFileBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectFileBasis&>(_nullElement());
}
/**
* Get AutoConnectInputBasis element.
* @param name An element name.
* @return A reference of AutoConnectInput class.
*/
template<>
AutoConnectInputBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Input)
return *(reinterpret_cast<AutoConnectInputBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectInputBasis&>(_nullElement());
}
/**
* Get AutoConnectRadioBasis element.
* @param name An element name.
* @return A reference of AutoConnectRadio class.
*/
template<>
AutoConnectRadioBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Radio)
return *(reinterpret_cast<AutoConnectRadioBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectRadioBasis&>(_nullElement());
}
/**
* Get AutoConnectSelectBasis element.
* @param name An element name.
* @return A reference of AutoConnectSelect class.
*/
template<>
AutoConnectSelectBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Select)
return *(reinterpret_cast<AutoConnectSelectBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectSelectBasis&>(_nullElement());
}
/**
* Get AutoConnectSubmitBasis element.
* @param name An element name.
* @return A reference of AutoConnectSubmit class.
*/
template<>
AutoConnectSubmitBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Submit)
return *(reinterpret_cast<AutoConnectSubmitBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectSubmitBasis&>(_nullElement());
}
/**
* Get AutoConnectTextBasis element.
* @param name An element name.
* @return A reference of AutoConnectText class.
*/
template<>
AutoConnectTextBasis& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Text)
return *(reinterpret_cast<AutoConnectTextBasis*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectTextBasis&>(_nullElement());
}
#else
/**
* Parse and load a JSON document which marks up multiple custom web
* pages. The compiler instantiates this template according to the stored
* data type that contains the JSON document.
* This template also generates different parsing function calls
* depending on the ArduinoJson version.
* @param T An object type of the JSON document which must be a
* passable object to ArduinoJson.
* @param in An instance of a source JSON document to load.
*/
template<typename T>
bool AutoConnect::_parseJson(T in) {
ArduinoJsonBuffer jsonBuffer(AUTOCONNECT_JSONBUFFER_PRIMITIVE_SIZE);
JsonVariant jv;
#if ARDUINOJSON_VERSION_MAJOR<=5
jv = jsonBuffer.parse(in);
if (!jv.success()) {
AC_DBG("JSON parse error\n");
return false;
}
#else
DeserializationError err = deserializeJson(jsonBuffer, in);
if (err) {
AC_DBG("Deserialize error:%s\n", err.c_str());
return false;
}
jv = jsonBuffer.as<JsonVariant>();
#endif
return _load(jv);
}
/**
* Parse and load a JSON document which marks up a custom web page.
* The compiler instantiates this template according to the stored data
* type that contains the JSON document.
* This template also generates different parsing function calls
* depending on the ArduinoJson version.
* @param T An object type of the JSON document which must be a
* passable object to ArduinoJson.
* @param in An instance of a source JSON document to load.
*/
template<typename T>
bool AutoConnectAux::_parseJson(T in) {
ArduinoJsonBuffer jsonBuffer(AUTOCONNECT_JSONBUFFER_PRIMITIVE_SIZE);
#if ARDUINOJSON_VERSION_MAJOR<=5
JsonObject& jb = jsonBuffer.parseObject(in);
if (!jb.success()) {
AC_DBG("JSON parse error\n");
return false;
}
#else
DeserializationError err = deserializeJson(jsonBuffer, in);
if (err) {
AC_DBG("Deserialize:%s\n", err.c_str());
return false;
}
JsonObject jb = jsonBuffer.as<JsonObject>();
#endif
return _load(jb);
}
/**
* Parse and load a JSON document which declares one of the AutoConnectElement.
* The compiler instantiates this template according to the stored data
* type that contains the JSON document.
* This template also generates different parsing function calls
* depending on the ArduinoJson version.
* @param T An object type of the JSON document which must be a
* passable object to ArduinoJson.
* @param in An instance of a source JSON document to load.
*/
template<typename T>
bool AutoConnectAux::_parseElement(T in, const String& name) {
ArduinoJsonBuffer jsonBuffer(AUTOCONNECT_JSONBUFFER_PRIMITIVE_SIZE);
JsonVariant jb;
#if ARDUINOJSON_VERSION_MAJOR<=5
jb = jsonBuffer.parse(in);
if (!jb.success()) {
AC_DBG("JSON parse error\n");
return false;
}
#else
DeserializationError err = deserializeJson(jsonBuffer, in);
if (err) {
AC_DBG("Deserialize:%s\n", err.c_str());
return false;
}
jb = jsonBuffer.as<JsonObject>();
#endif
return _loadElement(jb, name);
}
/**
* Get AutoConnectElementJson element.
* @param name an element name.
* @return A reference of AutoConnectElement class.
*/
template<>
AutoConnectElementJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
return *(reinterpret_cast<AutoConnectElementJson*>(elm));
}
return reinterpret_cast<AutoConnectElementJson&>(_nullElement());
}
/**
* Get AutoConnectButtonJson element.
* @param name An element name.
* @return A reference of AutoConnectButton class.
*/
template<>
AutoConnectButtonJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Button)
return *(reinterpret_cast<AutoConnectButtonJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectButtonJson&>(_nullElement());
}
/**
* Get AutoConnectCheckboxJson element.
* @param name An element name.
* @return A reference of AutoConnectCheckbox class.
*/
template<>
AutoConnectCheckboxJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Checkbox)
return *(reinterpret_cast<AutoConnectCheckboxJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectCheckboxJson&>(_nullElement());
}
/**
* Get AutoConnectFile element.
* @param name An element name.
* @return A reference of AutoConnectFile class.
*/
template<>
AutoConnectFileJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_File)
return *(reinterpret_cast<AutoConnectFileJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectFileJson&>(_nullElement());
}
/**
* Get AutoConnectInputJson element.
* @param name An element name.
* @return A reference of AutoConnectInput class.
*/
template<>
AutoConnectInputJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Input)
return *(reinterpret_cast<AutoConnectInputJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectInputJson&>(_nullElement());
}
/**
* Get AutoConnectRadioJson element.
* @param name An element name.
* @return A reference of AutoConnectRadio class.
*/
template<>
AutoConnectRadioJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Radio)
return *(reinterpret_cast<AutoConnectRadioJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectRadioJson&>(_nullElement());
}
/**
* Get AutoConnectSelectJson element.
* @param name An element name.
* @return A reference of AutoConnectSelect class.
*/
template<>
AutoConnectSelectJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Select)
return *(reinterpret_cast<AutoConnectSelectJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectSelectJson&>(_nullElement());
}
/**
* Get AutoConnectSubmitJson element.
* @param name An element name.
* @return A reference of AutoConnectSubmit class.
*/
template<>
AutoConnectSubmitJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Submit)
return *(reinterpret_cast<AutoConnectSubmitJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectSubmitJson&>(_nullElement());
}
/**
* Get AutoConnectTextJson element.
* @param name An element name.
* @return A reference of AutoConnectText class.
*/
template<>
AutoConnectTextJson& AutoConnectAux::getElement(const String& name) {
AutoConnectElement* elm = getElement(name);
if (elm) {
if (elm->typeOf() == AC_Text)
return *(reinterpret_cast<AutoConnectTextJson*>(elm));
else
AC_DBG("Element<%s> type mismatch<%d>\n", name.c_str(), elm->typeOf());
}
return reinterpret_cast<AutoConnectTextJson&>(_nullElement());
}
#endif // !AUTOCONNECT_USE_JSON
#endif // !_AUTOCONNECTAUXIMPL_H_

@ -149,6 +149,18 @@
#define AUTOCONNECT_SD_SPEED 4000000 #define AUTOCONNECT_SD_SPEED 4000000
#endif #endif
#endif // !AUTOCONNECT_SD_SPEED #endif // !AUTOCONNECT_SD_SPEED
// ArduinoJson buffer size
#ifndef AUTOCONNECT_JSONBUFFER_SIZE
#define AUTOCONNECT_JSONBUFFER_SIZE 256
#endif // !AUTOCONNECT_JSONBUFFER_SIZE
#ifndef AUTOCONNECT_JSONDOCUMENT_SIZE
#define AUTOCONNECT_JSONDOCUMENT_SIZE (8 * 1024)
#endif // !AUTOCONNECT_JSONDOCUMENT_SIZE
#ifndef AUTOCONNECT_JSONPSRAM_SIZE
#define AUTOCONNECT_JSONPSRAM_SIZE (16* 1024)
#endif // !AUTOCONNECT_JSONPSRAM_SIZE
// Explicitly avoiding unused warning with token handler of PageBuilder // Explicitly avoiding unused warning with token handler of PageBuilder
#define AC_UNUSED(expr) do { (void)(expr); } while (0) #define AC_UNUSED(expr) do { (void)(expr); } while (0)

@ -52,6 +52,10 @@ class AutoConnectElementBasis {
virtual ~AutoConnectElementBasis() {} virtual ~AutoConnectElementBasis() {}
virtual const String toHTML(void) const { return value; } virtual const String toHTML(void) const { return value; }
ACElement_t typeOf(void) const { return _type; } ACElement_t typeOf(void) const { return _type; }
#ifndef AUTOCONNECT_USE_JSON
template<typename T>
T& as(void);
#endif
String name; /**< Element name */ String name; /**< Element name */
String value; /**< Element value */ String value; /**< Element value */
@ -249,4 +253,66 @@ class AutoConnectTextBasis : virtual public AutoConnectElementBasis {
String format; /**< C string that contains the text to be written */ String format; /**< C string that contains the text to be written */
}; };
#ifndef AUTOCONNECT_USE_JSON
/**
* Casts only a class derived from the AutoConnectElement class to the
* actual element class.
*/
template<>
inline AutoConnectButtonBasis& AutoConnectElementBasis::as<AutoConnectButtonBasis>(void) {
if (typeOf() != AC_Button)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectButtonBasis*>(this));
}
template<>
inline AutoConnectCheckboxBasis& AutoConnectElementBasis::as<AutoConnectCheckboxBasis>(void) {
if (typeOf() != AC_Checkbox)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectCheckboxBasis*>(this));
}
template<>
inline AutoConnectFileBasis& AutoConnectElementBasis::as<AutoConnectFileBasis>(void) {
if (typeOf() != AC_File)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectFileBasis*>(this));
}
template<>
inline AutoConnectInputBasis& AutoConnectElementBasis::as<AutoConnectInputBasis>(void) {
if (typeOf() != AC_Input)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectInputBasis*>(this));
}
template<>
inline AutoConnectRadioBasis& AutoConnectElementBasis::as<AutoConnectRadioBasis>(void) {
if (typeOf() != AC_Radio)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectRadioBasis*>(this));
}
template<>
inline AutoConnectSelectBasis& AutoConnectElementBasis::as<AutoConnectSelectBasis>(void) {
if (typeOf() != AC_Select)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectSelectBasis*>(this));
}
template<>
inline AutoConnectSubmitBasis& AutoConnectElementBasis::as<AutoConnectSubmitBasis>(void) {
if (typeOf() != AC_Submit)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectSubmitBasis*>(this));
}
template<>
inline AutoConnectTextBasis& AutoConnectElementBasis::as<AutoConnectTextBasis>(void) {
if (typeOf() != AC_Text)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectTextBasis*>(this));
}
#endif
#endif // _AUTOCONNECTELEMENTBASIS_H_ #endif // _AUTOCONNECTELEMENTBASIS_H_

@ -19,6 +19,66 @@
#endif #endif
#include "AutoConnectElementBasis.h" #include "AutoConnectElementBasis.h"
/**
* Casts only a class derived from the AutoConnectElement class to the
* actual element class.
*/
// template<>
// inline AutoConnectButtonBasis& AutoConnectElementBasis::as(void) {
// if (typeOf() != AC_Button)
// AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
// return reinterpret_cast<AutoConnectButtonBasis&>(*this);
// }
// template<>
// inline AutoConnectCheckboxBasis& AutoConnectElementBasis::as(void) {
// if (typeOf() != AC_Checkbox)
// AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
// return reinterpret_cast<AutoConnectCheckboxBasis&>(*this);
// }
// template<>
// inline AutoConnectFileBasis& AutoConnectElementBasis::as(void) {
// if (typeOf() != AC_File)
// AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
// return reinterpret_cast<AutoConnectFileBasis&>(*this);
// }
// template<>
// inline AutoConnectInputBasis& AutoConnectElementBasis::as(void) {
// if (typeOf() != AC_Input)
// AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
// return reinterpret_cast<AutoConnectInputBasis&>(*this);
// }
// template<>
// inline AutoConnectRadioBasis& AutoConnectElementBasis::as(void) {
// if (typeOf() != AC_Radio)
// AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
// return reinterpret_cast<AutoConnectRadioBasis&>(*this);
// }
// template<>
// inline AutoConnectSelectBasis& AutoConnectElementBasis::as(void) {
// if (typeOf() != AC_Select)
// AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
// return reinterpret_cast<AutoConnectSelectBasis&>(*this);
// }
// template<>
// inline AutoConnectSubmitBasis& AutoConnectElementBasis::as(void) {
// if (typeOf() != AC_Submit)
// AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
// return reinterpret_cast<AutoConnectSubmitBasis&>(*this);
// }
// template<>
// inline AutoConnectTextBasis& AutoConnectElementBasis::as(void) {
// if (typeOf() != AC_Text)
// AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
// return reinterpret_cast<AutoConnectTextBasis&>(*this);
// }
/** /**
* Generate an HTML <button> element. The onclick behavior depends on * Generate an HTML <button> element. The onclick behavior depends on
* the code held in factionf member. * the code held in factionf member.

@ -2,8 +2,8 @@
* Declaration of AutoConnectElement extended classes using JSON. * Declaration of AutoConnectElement extended classes using JSON.
* @file AutoConnectElementJson.h * @file AutoConnectElementJson.h
* @author hieromon@gmail.com * @author hieromon@gmail.com
* @version 0.9.7 * @version 0.9.8
* @date 2018-11-17 * @date 2019-03-11
* @copyright MIT license. * @copyright MIT license.
*/ */
@ -45,6 +45,50 @@
#define AUTOCONNECT_JSON_VALUE_SD "sd" #define AUTOCONNECT_JSON_VALUE_SD "sd"
#define AUTOCONNECT_JSON_VALUE_VERTICAL "vertical" #define AUTOCONNECT_JSON_VALUE_VERTICAL "vertical"
/**
* Make the Json types and functions consistent with the ArduinoJson
* version. These declarations share the following type definitions:
* - Difference between reference and proxy of JsonObject and JsonArray.
* - Difference of check whether the parsing succeeded or not.
* - The print function name difference.
* - The buffer class difference.
* - When PSRAM present, enables the buffer allocation it with ESP32 and
* supported version.
*/
#if ARDUINOJSON_VERSION_MAJOR<=5
#define ARDUINOJSON_CREATEOBJECT(doc) doc.createObject()
#define ARDUINOJSON_CREATEARRAY(doc) doc.createArray()
#define ARDUINOJSON_PRETTYPRINT(doc, out) ({ size_t s = doc.prettyPrintTo(out); s; })
#define ARDUINOJSON_PRINT(doc, out) ({ size_t s = doc.printTo(out); s; })
using ArduinoJsonObject = JsonObject&;
using ArduinoJsonArray = JsonArray&;
using ArduinoJsonBuffer = DynamicJsonBuffer;
#define AUTOCONNECT_JSONBUFFER_PRIMITIVE_SIZE AUTOCONNECT_JSONBUFFER_SIZE
#else
#define ARDUINOJSON_CREATEOBJECT(doc) doc.to<JsonObject>()
#define ARDUINOJSON_CREATEARRAY(doc) doc.to<JsonArray>()
#define ARDUINOJSON_PRETTYPRINT(doc, out) ({ size_t s = serializeJsonPretty(doc, out); s; })
#define ARDUINOJSON_PRINT(doc, out) ({ size_t s = serializeJson(doc, out); s; })
using ArduinoJsonObject = JsonObject;
using ArduinoJsonArray = JsonArray;
#if defined(BOARD_HAS_PSRAM) && ((ARDUINOJSON_VERSION_MAJOR==6 && ARDUINOJSON_VERSION_MINOR>=10) || ARDUINOJSON_VERSION_MAJOR>6)
// JsonDocument is assigned to PSRAM by ArduinoJson's custom allocator.
struct SpiRamAllocatorST {
void* allocate(size_t size) {
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
}
void deallocate(void* pointer) {
heap_caps_free(pointer);
}
};
#define AUTOCONNECT_JSONBUFFER_PRIMITIVE_SIZE AUTOCONNECT_JSONPSRAM_SIZE
using ArduinoJsonBuffer = BasicJsonDocument<SpiRamAllocatorST>;
#else
#define AUTOCONNECT_JSONBUFFER_PRIMITIVE_SIZE AUTOCONNECT_JSONDOCUMENT_SIZE
using ArduinoJsonBuffer = DynamicJsonDocument;
#endif
#endif
/** /**
* AutoConnectAux element base with handling with JSON object. * AutoConnectAux element base with handling with JSON object.
* Placed a raw text that can be added by user sketch. * Placed a raw text that can be added by user sketch.
@ -61,6 +105,8 @@ class AutoConnectElementJson : virtual public AutoConnectElementBasis {
virtual size_t getObjectSize(void) const; virtual size_t getObjectSize(void) const;
virtual bool loadMember(const JsonObject& json); virtual bool loadMember(const JsonObject& json);
virtual void serialize(JsonObject& json); virtual void serialize(JsonObject& json);
template<typename T>
T& as(void);
protected: protected:
void _setMember(const JsonObject& json); void _setMember(const JsonObject& json);
@ -247,4 +293,64 @@ class AutoConnectTextJson : public AutoConnectElementJson, public AutoConnectTex
void serialize(JsonObject& json) override; void serialize(JsonObject& json) override;
}; };
/**
* Casts only a class derived from the AutoConnectElement class to the
* actual element class.
*/
template<>
inline AutoConnectButtonJson& AutoConnectElementJson::as<AutoConnectButtonJson>(void) {
if (typeOf() != AC_Button)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectButtonJson*>(this));
}
template<>
inline AutoConnectCheckboxJson& AutoConnectElementJson::as<AutoConnectCheckboxJson>(void) {
if (typeOf() != AC_Checkbox)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectCheckboxJson*>(this));
}
template<>
inline AutoConnectFileJson& AutoConnectElementJson::as<AutoConnectFileJson>(void) {
if (typeOf() != AC_File)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectFileJson*>(this));
}
template<>
inline AutoConnectInputJson& AutoConnectElementJson::as<AutoConnectInputJson>(void) {
if (typeOf() != AC_Input)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectInputJson*>(this));
}
template<>
inline AutoConnectRadioJson& AutoConnectElementJson::as<AutoConnectRadioJson>(void) {
if (typeOf() != AC_Radio)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectRadioJson*>(this));
}
template<>
inline AutoConnectSelectJson& AutoConnectElementJson::as<AutoConnectSelectJson>(void) {
if (typeOf() != AC_Select)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectSelectJson*>(this));
}
template<>
inline AutoConnectSubmitJson& AutoConnectElementJson::as<AutoConnectSubmitJson>(void) {
if (typeOf() != AC_Submit)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectSubmitJson*>(this));
}
template<>
inline AutoConnectTextJson& AutoConnectElementJson::as<AutoConnectTextJson>(void) {
if (typeOf() != AC_Text)
AC_DBG("%s mismatched type as <%d>\n", name.c_str(), (int)typeOf());
return *(reinterpret_cast<AutoConnectTextJson*>(this));
}
#endif // _AUTOCONNECTELEMENTJSON_H_ #endif // _AUTOCONNECTELEMENTJSON_H_

@ -27,7 +27,7 @@ size_t AutoConnectElementJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched. * @return false Type of AutoConnectElement is mismatched.
*/ */
bool AutoConnectElementJson::loadMember(const JsonObject& json) { bool AutoConnectElementJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE)); String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACELEMENT))) { if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACELEMENT))) {
_setMember(json); _setMember(json);
return true; return true;
@ -41,8 +41,8 @@ bool AutoConnectElementJson::loadMember(const JsonObject& json) {
*/ */
void AutoConnectElementJson::serialize(JsonObject& json) { void AutoConnectElementJson::serialize(JsonObject& json) {
_serialize(json); _serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACELEMENT)); json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACELEMENT));
json.set(F(AUTOCONNECT_JSON_KEY_VALUE), value); json[F(AUTOCONNECT_JSON_KEY_VALUE)] = value;
} }
/** /**
@ -51,7 +51,7 @@ void AutoConnectElementJson::serialize(JsonObject& json) {
* @param json JSON object to be serialized. * @param json JSON object to be serialized.
*/ */
void AutoConnectElementJson::_serialize(JsonObject& json) { void AutoConnectElementJson::_serialize(JsonObject& json) {
json.set(F(AUTOCONNECT_JSON_KEY_NAME), name); json[F(AUTOCONNECT_JSON_KEY_NAME)] = name;
} }
/** /**
@ -59,9 +59,9 @@ void AutoConnectElementJson::_serialize(JsonObject& json) {
* @param json JSON object with the definition of AutoConnectElement. * @param json JSON object with the definition of AutoConnectElement.
*/ */
void AutoConnectElementJson::_setMember(const JsonObject& json) { void AutoConnectElementJson::_setMember(const JsonObject& json) {
name = json.get<String>(F(AUTOCONNECT_JSON_KEY_NAME)); name = json[F(AUTOCONNECT_JSON_KEY_NAME)].as<String>();
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_VALUE))) if (json.containsKey(F(AUTOCONNECT_JSON_KEY_VALUE)))
value = json.get<String>(F(AUTOCONNECT_JSON_KEY_VALUE)); value = json[F(AUTOCONNECT_JSON_KEY_VALUE)].as<String>();
} }
/** /**
@ -79,11 +79,11 @@ size_t AutoConnectButtonJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched. * @return false Type of AutoConnectElement is mismatched.
*/ */
bool AutoConnectButtonJson::loadMember(const JsonObject& json) { bool AutoConnectButtonJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE)); String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACBUTTON))) { if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACBUTTON))) {
_setMember(json); _setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_ACTION))) if (json.containsKey(F(AUTOCONNECT_JSON_KEY_ACTION)))
action = json.get<String>(F(AUTOCONNECT_JSON_KEY_ACTION)); action = json[F(AUTOCONNECT_JSON_KEY_ACTION)].as<String>();
return true; return true;
} }
return false; return false;
@ -95,9 +95,9 @@ bool AutoConnectButtonJson::loadMember(const JsonObject& json) {
*/ */
void AutoConnectButtonJson::serialize(JsonObject& json) { void AutoConnectButtonJson::serialize(JsonObject& json) {
_serialize(json); _serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACBUTTON)); json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACBUTTON));
json.set(F(AUTOCONNECT_JSON_KEY_VALUE), value); json[F(AUTOCONNECT_JSON_KEY_VALUE)] = value;
json.set(F(AUTOCONNECT_JSON_KEY_ACTION), action); json[F(AUTOCONNECT_JSON_KEY_ACTION)] = action;
} }
/** /**
@ -115,13 +115,13 @@ size_t AutoConnectCheckboxJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched. * @return false Type of AutoConnectElement is mismatched.
*/ */
bool AutoConnectCheckboxJson::loadMember(const JsonObject& json) { bool AutoConnectCheckboxJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE)); String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACCHECKBOX))) { if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACCHECKBOX))) {
_setMember(json); _setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_LABEL))) if (json.containsKey(F(AUTOCONNECT_JSON_KEY_LABEL)))
label = json.get<String>(F(AUTOCONNECT_JSON_KEY_LABEL)); label = json[F(AUTOCONNECT_JSON_KEY_LABEL)].as<String>();
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_CHECKED))) if (json.containsKey(F(AUTOCONNECT_JSON_KEY_CHECKED)))
checked = json.get<bool>(F(AUTOCONNECT_JSON_KEY_CHECKED)); checked = json[F(AUTOCONNECT_JSON_KEY_CHECKED)].as<bool>();
return true; return true;
} }
return false; return false;
@ -133,11 +133,11 @@ bool AutoConnectCheckboxJson::loadMember(const JsonObject& json) {
*/ */
void AutoConnectCheckboxJson::serialize(JsonObject& json) { void AutoConnectCheckboxJson::serialize(JsonObject& json) {
_serialize(json); _serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACCHECKBOX)); json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACCHECKBOX));
json.set(F(AUTOCONNECT_JSON_KEY_NAME), name); json[F(AUTOCONNECT_JSON_KEY_NAME)] = name;
json.set(F(AUTOCONNECT_JSON_KEY_VALUE), value); json[F(AUTOCONNECT_JSON_KEY_VALUE)] = value;
json.set(F(AUTOCONNECT_JSON_KEY_LABEL), label); json[F(AUTOCONNECT_JSON_KEY_LABEL)] = label;
json.set(F(AUTOCONNECT_JSON_KEY_CHECKED), checked); json[F(AUTOCONNECT_JSON_KEY_CHECKED)] = checked;
} }
/** /**
@ -155,13 +155,13 @@ size_t AutoConnectFileJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched. * @return false Type of AutoConnectElement is mismatched.
*/ */
bool AutoConnectFileJson::loadMember(const JsonObject& json) { bool AutoConnectFileJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE)); String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACFILE))) { if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACFILE))) {
_setMember(json); _setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_LABEL))) if (json.containsKey(F(AUTOCONNECT_JSON_KEY_LABEL)))
label = json.get<String>(F(AUTOCONNECT_JSON_KEY_LABEL)); label = json[F(AUTOCONNECT_JSON_KEY_LABEL)].as<String>();
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_STORE))) { if (json.containsKey(F(AUTOCONNECT_JSON_KEY_STORE))) {
String media = json.get<String>(F(AUTOCONNECT_JSON_KEY_STORE)); String media = json[F(AUTOCONNECT_JSON_KEY_STORE)].as<String>();
if (media.equalsIgnoreCase(F(AUTOCONNECT_JSON_VALUE_FS))) if (media.equalsIgnoreCase(F(AUTOCONNECT_JSON_VALUE_FS)))
store = AC_File_FS; store = AC_File_FS;
else if (media.equalsIgnoreCase(F(AUTOCONNECT_JSON_VALUE_SD))) else if (media.equalsIgnoreCase(F(AUTOCONNECT_JSON_VALUE_SD)))
@ -184,18 +184,18 @@ bool AutoConnectFileJson::loadMember(const JsonObject& json) {
*/ */
void AutoConnectFileJson::serialize(JsonObject& json) { void AutoConnectFileJson::serialize(JsonObject& json) {
_serialize(json); _serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACFILE)); json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACFILE));
json.set(F(AUTOCONNECT_JSON_KEY_VALUE), value); json[F(AUTOCONNECT_JSON_KEY_VALUE)] = value;
json.set(F(AUTOCONNECT_JSON_KEY_LABEL), label); json[F(AUTOCONNECT_JSON_KEY_LABEL)] = label;
switch (store) { switch (store) {
case AC_File_FS: case AC_File_FS:
json.set(F(AUTOCONNECT_JSON_KEY_STORE), AUTOCONNECT_JSON_VALUE_FS); json[F(AUTOCONNECT_JSON_KEY_STORE)] = AUTOCONNECT_JSON_VALUE_FS;
break; break;
case AC_File_SD: case AC_File_SD:
json.set(F(AUTOCONNECT_JSON_KEY_STORE), AUTOCONNECT_JSON_VALUE_SD); json[F(AUTOCONNECT_JSON_KEY_STORE)] = AUTOCONNECT_JSON_VALUE_SD;
break; break;
case AC_File_Ext: case AC_File_Ext:
json.set(F(AUTOCONNECT_JSON_KEY_STORE), AUTOCONNECT_JSON_VALUE_EXTERNAL); json[F(AUTOCONNECT_JSON_KEY_STORE)] = AUTOCONNECT_JSON_VALUE_EXTERNAL;
break; break;
} }
} }
@ -215,15 +215,15 @@ size_t AutoConnectInputJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched. * @return false Type of AutoConnectElement is mismatched.
*/ */
bool AutoConnectInputJson::loadMember(const JsonObject& json) { bool AutoConnectInputJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE)); String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACINPUT))) { if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACINPUT))) {
_setMember(json); _setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_LABEL))) if (json.containsKey(F(AUTOCONNECT_JSON_KEY_LABEL)))
label = json.get<String>(F(AUTOCONNECT_JSON_KEY_LABEL)); label = json[F(AUTOCONNECT_JSON_KEY_LABEL)].as<String>();
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_PATTERN))) if (json.containsKey(F(AUTOCONNECT_JSON_KEY_PATTERN)))
pattern = json.get<String>(F(AUTOCONNECT_JSON_KEY_PATTERN)); pattern = json[F(AUTOCONNECT_JSON_KEY_PATTERN)].as<String>();
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_PLACEHOLDER))) if (json.containsKey(F(AUTOCONNECT_JSON_KEY_PLACEHOLDER)))
placeholder = json.get<String>(F(AUTOCONNECT_JSON_KEY_PLACEHOLDER)); placeholder = json[F(AUTOCONNECT_JSON_KEY_PLACEHOLDER)].as<String>();
return true; return true;
} }
return false; return false;
@ -235,11 +235,11 @@ bool AutoConnectInputJson::loadMember(const JsonObject& json) {
*/ */
void AutoConnectInputJson::serialize(JsonObject& json) { void AutoConnectInputJson::serialize(JsonObject& json) {
_serialize(json); _serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACINPUT)); json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACINPUT));
json.set(F(AUTOCONNECT_JSON_KEY_VALUE), value); json[F(AUTOCONNECT_JSON_KEY_VALUE)] = value;
json.set(F(AUTOCONNECT_JSON_KEY_LABEL), label); json[F(AUTOCONNECT_JSON_KEY_LABEL)] = label;
json.set(F(AUTOCONNECT_JSON_KEY_PATTERN), pattern); json[F(AUTOCONNECT_JSON_KEY_PATTERN)] = pattern;
json.set(F(AUTOCONNECT_JSON_KEY_PLACEHOLDER), placeholder); json[F(AUTOCONNECT_JSON_KEY_PLACEHOLDER)] = placeholder;
} }
/** /**
@ -257,15 +257,15 @@ size_t AutoConnectRadioJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched. * @return false Type of AutoConnectElement is mismatched.
*/ */
bool AutoConnectRadioJson::loadMember(const JsonObject& json) { bool AutoConnectRadioJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE)); String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACRADIO))) { if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACRADIO))) {
_setMember(json); _setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_LABEL))) if (json.containsKey(F(AUTOCONNECT_JSON_KEY_LABEL)))
label = json.get<String>(F(AUTOCONNECT_JSON_KEY_LABEL)); label = json[F(AUTOCONNECT_JSON_KEY_LABEL)].as<String>();
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_CHECKED))) if (json.containsKey(F(AUTOCONNECT_JSON_KEY_CHECKED)))
checked = static_cast<uint8_t>(json.get<int>(F(AUTOCONNECT_JSON_KEY_CHECKED))); checked = static_cast<uint8_t>(json[F(AUTOCONNECT_JSON_KEY_CHECKED)].as<int>());
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_ARRANGE))) { if (json.containsKey(F(AUTOCONNECT_JSON_KEY_ARRANGE))) {
String arrange = json.get<String>(F(AUTOCONNECT_JSON_KEY_ARRANGE)); String arrange = json[F(AUTOCONNECT_JSON_KEY_ARRANGE)].as<String>();
if (arrange.equalsIgnoreCase(F(AUTOCONNECT_JSON_VALUE_VERTICAL))) if (arrange.equalsIgnoreCase(F(AUTOCONNECT_JSON_VALUE_VERTICAL)))
order = AC_Vertical; order = AC_Vertical;
else if (arrange.equalsIgnoreCase(F(AUTOCONNECT_JSON_VALUE_HORIZONTAL))) else if (arrange.equalsIgnoreCase(F(AUTOCONNECT_JSON_VALUE_HORIZONTAL)))
@ -277,7 +277,8 @@ bool AutoConnectRadioJson::loadMember(const JsonObject& json) {
} }
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_VALUE))) { if (json.containsKey(F(AUTOCONNECT_JSON_KEY_VALUE))) {
empty(); empty();
JsonArray& optionArray = json[AUTOCONNECT_JSON_KEY_VALUE]; // JsonArray& optionArray = json[AUTOCONNECT_JSON_KEY_VALUE];
ArduinoJsonArray optionArray = json[AUTOCONNECT_JSON_KEY_VALUE];
for (auto value : optionArray) for (auto value : optionArray)
add(value.as<String>()); add(value.as<String>());
} }
@ -292,20 +293,20 @@ bool AutoConnectRadioJson::loadMember(const JsonObject& json) {
*/ */
void AutoConnectRadioJson::serialize(JsonObject& json) { void AutoConnectRadioJson::serialize(JsonObject& json) {
_serialize(json); _serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACRADIO)); json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACRADIO));
json.set(F(AUTOCONNECT_JSON_KEY_LABEL), label); json[F(AUTOCONNECT_JSON_KEY_LABEL)] = label;
JsonArray& values = json.createNestedArray(F(AUTOCONNECT_JSON_KEY_VALUE)); ArduinoJsonArray values = json.createNestedArray(F(AUTOCONNECT_JSON_KEY_VALUE));
for (String v : _values) for (String v : _values)
values.add(v); values.add(v);
switch (order) { switch (order) {
case AC_Horizontal: case AC_Horizontal:
json.set(F(AUTOCONNECT_JSON_KEY_ARRANGE), AUTOCONNECT_JSON_VALUE_HORIZONTAL); json[F(AUTOCONNECT_JSON_KEY_ARRANGE)] = String(F(AUTOCONNECT_JSON_VALUE_HORIZONTAL));
break; break;
case AC_Vertical: case AC_Vertical:
json.set(F(AUTOCONNECT_JSON_KEY_ARRANGE), AUTOCONNECT_JSON_VALUE_VERTICAL); json[F(AUTOCONNECT_JSON_KEY_ARRANGE)] = String(F(AUTOCONNECT_JSON_VALUE_VERTICAL));
break; break;
} }
json.set(F(AUTOCONNECT_JSON_KEY_CHECKED), checked); json[F(AUTOCONNECT_JSON_KEY_CHECKED)] = checked;
} }
/** /**
@ -323,15 +324,15 @@ size_t AutoConnectSelectJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched. * @return false Type of AutoConnectElement is mismatched.
*/ */
bool AutoConnectSelectJson::loadMember(const JsonObject& json) { bool AutoConnectSelectJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE)); String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACSELECT))) { if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACSELECT))) {
_setMember(json); _setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_LABEL))) { if (json.containsKey(F(AUTOCONNECT_JSON_KEY_LABEL))) {
label = json.get<String>(F(AUTOCONNECT_JSON_KEY_LABEL)); label = json[F(AUTOCONNECT_JSON_KEY_LABEL)].as<String>();
} }
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_OPTION))) { if (json.containsKey(F(AUTOCONNECT_JSON_KEY_OPTION))) {
empty(); empty();
JsonArray& optionArray = json[AUTOCONNECT_JSON_KEY_OPTION]; ArduinoJsonArray optionArray = json[AUTOCONNECT_JSON_KEY_OPTION];
for (auto value : optionArray) for (auto value : optionArray)
add(value.as<String>()); add(value.as<String>());
return true; return true;
@ -346,11 +347,11 @@ bool AutoConnectSelectJson::loadMember(const JsonObject& json) {
*/ */
void AutoConnectSelectJson::serialize(JsonObject& json) { void AutoConnectSelectJson::serialize(JsonObject& json) {
_serialize(json); _serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACSELECT)); json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACSELECT));
JsonArray& options = json.createNestedArray(F(AUTOCONNECT_JSON_KEY_OPTION)); ArduinoJsonArray options = json.createNestedArray(F(AUTOCONNECT_JSON_KEY_OPTION));
for (String o : _options) for (String o : _options)
options.add(o); options.add(o);
json.set(F(AUTOCONNECT_JSON_KEY_LABEL), label); json[F(AUTOCONNECT_JSON_KEY_LABEL)] = label;
} }
/** /**
@ -368,11 +369,11 @@ size_t AutoConnectSubmitJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched. * @return false Type of AutoConnectElement is mismatched.
*/ */
bool AutoConnectSubmitJson::loadMember(const JsonObject& json) { bool AutoConnectSubmitJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE)); String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACSUBMIT))) { if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACSUBMIT))) {
_setMember(json); _setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_URI))) if (json.containsKey(F(AUTOCONNECT_JSON_KEY_URI)))
uri = json.get<String>(F(AUTOCONNECT_JSON_KEY_URI)); uri = json[F(AUTOCONNECT_JSON_KEY_URI)].as<String>();
return true; return true;
} }
return false; return false;
@ -384,9 +385,9 @@ bool AutoConnectSubmitJson::loadMember(const JsonObject& json) {
*/ */
void AutoConnectSubmitJson::serialize(JsonObject& json) { void AutoConnectSubmitJson::serialize(JsonObject& json) {
_serialize(json); _serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACSUBMIT)); json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACSUBMIT));
json.set(F(AUTOCONNECT_JSON_KEY_VALUE), value); json[F(AUTOCONNECT_JSON_KEY_VALUE)] = value;
json.set(F(AUTOCONNECT_JSON_KEY_URI), uri); json[F(AUTOCONNECT_JSON_KEY_URI)] = uri;
} }
/** /**
@ -404,13 +405,13 @@ size_t AutoConnectTextJson::getObjectSize() const {
* @return false Type of AutoConnectElement is mismatched. * @return false Type of AutoConnectElement is mismatched.
*/ */
bool AutoConnectTextJson::loadMember(const JsonObject& json) { bool AutoConnectTextJson::loadMember(const JsonObject& json) {
String type = json.get<String>(F(AUTOCONNECT_JSON_KEY_TYPE)); String type = json[F(AUTOCONNECT_JSON_KEY_TYPE)].as<String>();
if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACTEXT))) { if (type.equalsIgnoreCase(F(AUTOCONNECT_JSON_TYPE_ACTEXT))) {
_setMember(json); _setMember(json);
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_STYLE))) if (json.containsKey(F(AUTOCONNECT_JSON_KEY_STYLE)))
style = json.get<String>(F(AUTOCONNECT_JSON_KEY_STYLE)); style = json[F(AUTOCONNECT_JSON_KEY_STYLE)].as<String>();
if (json.containsKey(F(AUTOCONNECT_JSON_KEY_FORMAT))) if (json.containsKey(F(AUTOCONNECT_JSON_KEY_FORMAT)))
format = json.get<String>(F(AUTOCONNECT_JSON_KEY_FORMAT)); format = json[F(AUTOCONNECT_JSON_KEY_FORMAT)].as<String>();
return true; return true;
} }
return false; return false;
@ -422,10 +423,10 @@ bool AutoConnectTextJson::loadMember(const JsonObject& json) {
*/ */
void AutoConnectTextJson::serialize(JsonObject& json) { void AutoConnectTextJson::serialize(JsonObject& json) {
_serialize(json); _serialize(json);
json.set(F(AUTOCONNECT_JSON_KEY_TYPE), F(AUTOCONNECT_JSON_TYPE_ACTEXT)); json[F(AUTOCONNECT_JSON_KEY_TYPE)] = String(F(AUTOCONNECT_JSON_TYPE_ACTEXT));
json.set(F(AUTOCONNECT_JSON_KEY_VALUE), value); json[F(AUTOCONNECT_JSON_KEY_VALUE)] = value;
json.set(F(AUTOCONNECT_JSON_KEY_STYLE), style); json[F(AUTOCONNECT_JSON_KEY_STYLE)] = style;
json.set(F(AUTOCONNECT_JSON_KEY_FORMAT), format); json[F(AUTOCONNECT_JSON_KEY_FORMAT)] = format;
} }
#endif // _AUTOCONNECTELEMENTJSONIMPL_H_ #endif // _AUTOCONNECTELEMENTJSONIMPL_H_

Loading…
Cancel
Save