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. 405
      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;
// Explicitly cast to the desired element to correctly extract
// the element using the operator [].
AutoConnectFile& filename = (AutoConnectFile&)auxUpload["filename"];
AutoConnectText& aux_filename = (AutoConnectText&)aux["filename"];
AutoConnectText& aux_size = (AutoConnectText&)aux["size"];
AutoConnectText& aux_contentType = (AutoConnectText&)aux["content_type"];
AutoConnectFile& filename = auxUpload["filename"].as<AutoConnectFile>();
AutoConnectText& aux_filename = aux["filename"].as<AutoConnectText>();
AutoConnectText& aux_size = aux["size"].as<AutoConnectText>();
AutoConnectText& aux_contentType = aux["content_type"].as<AutoConnectText>();
// Assignment operator can be used for the element attribute.
aux_filename.value = filename.value;
aux_size.value = String(filename.size);

@ -158,7 +158,7 @@ void setup() {
Timezone.load(AUX_TIMEZONE);
// Retrieve the select element that holds the time zone code and
// 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++) {
tz.add(String(TZ[n].zone));
}

@ -256,42 +256,38 @@ String loadParams(AutoConnectAux& aux, PageArgument& args) {
String saveParams(AutoConnectAux& aux, PageArgument& args) {
// The 'where()' function returns the AutoConnectAux that caused
// 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.trim();
AutoConnectInput& channelid = mqtt_setting->getElement<AutoConnectInput>("channelid");
channelId = channelid.value;
channelId = mqtt_setting["channelid"].value;
channelId.trim();
AutoConnectInput& userkey = mqtt_setting->getElement<AutoConnectInput>("userkey");
userKey = userkey.value;
userKey = mqtt_setting["userkey"].value;
userKey.trim();
AutoConnectInput& apikey = mqtt_setting->getElement<AutoConnectInput>("apikey");
apiKey = apikey.value;
apiKey = mqtt_setting["apikey"].value;
apiKey.trim();
AutoConnectRadio& period = mqtt_setting->getElement<AutoConnectRadio>("period");
AutoConnectRadio& period = mqtt_setting["period"].as<AutoConnectRadio>();
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 = hostname.value;
hostName = mqtt_setting["hostname"].value;
hostName.trim();
// The entered value is owned by AutoConnectAux of /mqtt_setting.
// To retrieve the elements of /mqtt_setting, it is necessary to get
// the AutoConnectAux object of /mqtt_setting.
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();
// 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 += mqttserver.isValid() ? String(" (OK)") : String(" (ERR)");
echo.value += "<br>Channel ID: " + channelId + "<br>";
@ -354,9 +350,9 @@ void setup() {
SPIFFS.begin();
if (portal.load(FPSTR(AUX_mqtt_setting))) {
AutoConnectAux* mqtt_setting = portal.aux(AUX_SETTING_URI);
AutoConnectCheckbox& uniqueidElm = mqtt_setting->getElement<AutoConnectCheckbox>("uniqueid");
AutoConnectInput& hostnameElm = mqtt_setting->getElement<AutoConnectInput>("hostname");
AutoConnectAux& mqtt_setting = *portal.aux(AUX_SETTING_URI);
AutoConnectCheckbox& uniqueidElm = mqtt_setting["uniqueid"].as<AutoConnectCheckbox>();
AutoConnectInput& hostnameElm = mqtt_setting["hostname"].as<AutoConnectInput>();
if (uniqueidElm.checked) {
config.apid = String("ESP") + "-" + String(GET_CHIPID(), HEX);
Serial.println("apid set to " + config.apid);

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

@ -185,7 +185,7 @@ class AutoConnect {
void join(AutoConnectAux& aux);
void join(AutoConnectAuxVT auxVector);
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 */
#ifdef AUTOCONNECT_USE_JSON
@ -220,6 +220,8 @@ class AutoConnect {
void _purgePages(void);
virtual PageElement* _setupPage(String uri);
#ifdef AUTOCONNECT_USE_JSON
template<typename T>
bool _parseJson(T in);
bool _load(JsonVariant& aux);
#endif // !AUTOCONNECT_USE_JSON

@ -9,8 +9,8 @@
#include <algorithm>
#include "AutoConnect.h"
#include "AutoConnectAux.h"
#include "AutoConnectAuxImpl.h"
#include "AutoConnectUploadImpl.h"
#include "AutoConnectElement.h"
#include "AutoConnectElementBasisImpl.h"
#ifdef AUTOCONNECT_USE_JSON
#include "AutoConnectElementJsonImpl.h"
@ -466,309 +466,7 @@ void AutoConnectAux::_storeElements(WebServerClass* webServer) {
}
}
#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
/**
* 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());
}
#ifdef AUTOCONNECT_USE_JSON
/**
* Load AutoConnectAux page from JSON description stored in the sketch.
@ -778,9 +476,7 @@ AutoConnectTextJson& AutoConnectAux::getElement(const String& name) {
* @return true Successfully loaded.
*/
bool AutoConnect::load(const String& aux) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonVariant jv = jsonBuffer.parse(aux);
return _load(jv);
return _parseJson<const String&>(aux);
}
/**
@ -791,9 +487,7 @@ bool AutoConnect::load(const String& aux) {
* @return true Successfully loaded.
*/
bool AutoConnect::load(const __FlashStringHelper* aux) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonVariant jv = jsonBuffer.parse(aux);
return _load(jv);
return _parseJson<const __FlashStringHelper*>(aux);
}
/**
@ -804,9 +498,7 @@ bool AutoConnect::load(const __FlashStringHelper* aux) {
* @return true Successfully loaded.
*/
bool AutoConnect::load(Stream& aux) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonVariant jv = jsonBuffer.parse(aux);
return _load(jv);
return _parseJson<Stream&>(aux);
}
/**
@ -815,11 +507,10 @@ bool AutoConnect::load(Stream& aux) {
* @return true Successfully loaded.
*/
bool AutoConnect::_load(JsonVariant& auxJson) {
bool rc = auxJson.success();
if (rc) {
bool rc = true;
if (auxJson.is<JsonArray>()) {
JsonArray& jb = auxJson.as<JsonArray>();
for (JsonObject& auxJson : jb) {
ArduinoJsonArray jb = auxJson.as<JsonArray>();
for (ArduinoJsonObject auxJson : jb) {
AutoConnectAux* newAux = new AutoConnectAux;
if (newAux->_load(auxJson))
join(*newAux);
@ -831,7 +522,7 @@ bool AutoConnect::_load(JsonVariant& auxJson) {
}
}
else {
JsonObject& jb = auxJson.as<JsonObject>();
ArduinoJsonObject jb = auxJson.as<JsonObject>();
AutoConnectAux* newAux = new AutoConnectAux;
if (newAux->_load(jb))
join(*newAux);
@ -840,10 +531,6 @@ bool AutoConnect::_load(JsonVariant& auxJson) {
rc = false;
}
}
}
else {
AC_DBG("JSON parse error\n");
}
return rc;
}
@ -854,7 +541,7 @@ bool AutoConnect::_load(JsonVariant& auxJson) {
*/
AutoConnectElement* AutoConnectAux::_createElement(const JsonObject& json) {
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)) {
case AC_Element:
@ -906,9 +593,7 @@ AutoConnectElement* AutoConnectAux::_createElement(const JsonObject& json) {
* @return false Invalid JSON data occurred.
*/
bool AutoConnectAux::load(const String& in) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonObject& jb = jsonBuffer.parseObject(in);
return _load(jb);
return _parseJson<const String&>(in);
}
/**
@ -920,9 +605,7 @@ bool AutoConnectAux::load(const String& in) {
* @return false Invalid JSON data occurred.
*/
bool AutoConnectAux::load(const __FlashStringHelper* in) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonObject& jb = jsonBuffer.parseObject(in);
return _load(jb);
return _parseJson<const __FlashStringHelper*>(in);
}
/**
@ -934,9 +617,7 @@ bool AutoConnectAux::load(const __FlashStringHelper* in) {
* @return false Invalid JSON data occurred.
*/
bool AutoConnectAux::load(Stream& in) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonObject& jb = jsonBuffer.parseObject(in);
return _load(jb);
return _parseJson<Stream&>(in);
}
/**
@ -946,15 +627,10 @@ bool AutoConnectAux::load(Stream& in) {
* @return false loading unsuccessful, JSON parsing error occurred.
*/
bool AutoConnectAux::_load(JsonObject& jb) {
if (!jb.success()) {
AC_DBG("json parse error\n");
return false;
}
_title = jb.get<String>(F(AUTOCONNECT_JSON_KEY_TITLE));
_uriStr = jb.get<String>(F(AUTOCONNECT_JSON_KEY_URI));
_title = jb[F(AUTOCONNECT_JSON_KEY_TITLE)].as<String>();
_uriStr = jb[F(AUTOCONNECT_JSON_KEY_URI)].as<String>();
_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)];
(void)_loadElement(elements, "");
return true;
@ -971,29 +647,22 @@ bool AutoConnectAux::_load(JsonObject& jb) {
* @return A reference of loaded AutoConnectElement instance.
*/
bool AutoConnectAux::loadElement(const String& in, const String& name) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonVariant jb = jsonBuffer.parse(in);
return _loadElement(jb, name);
return _parseElement<const String&>(in, name);
}
bool AutoConnectAux::loadElement(const __FlashStringHelper* in, const String& name) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonVariant jb = jsonBuffer.parse(in);
return _loadElement(jb, name);
return _parseElement<const __FlashStringHelper*>(in, name);
}
bool AutoConnectAux::loadElement(Stream& in, const String& name) {
DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonVariant jb = jsonBuffer.parse(in);
return _loadElement(jb, name);
return _parseElement<Stream&>(in, name);
}
bool AutoConnectAux::_loadElement(JsonVariant& jb, const String& name) {
bool rc = jb.success();
if (rc) {
bool rc = true;
if (jb.is<JsonArray>()) {
JsonArray& elements = jb.as<JsonArray>();
for (JsonObject& element : elements) {
ArduinoJsonArray elements = jb.as<JsonArray>();
for (ArduinoJsonObject element : elements) {
AutoConnectElement& elm = _loadElement(element, name);
if (!elm.name.length()) {
rc = false;
@ -1002,18 +671,17 @@ bool AutoConnectAux::_loadElement(JsonVariant& jb, const String& name) {
}
}
else {
JsonObject& element = jb.as<JsonObject>();
ArduinoJsonObject element = jb.as<JsonObject>();
AutoConnectElement& elm = _loadElement(element, name);
if (!elm.name.length())
rc = false;
}
}
return rc;
}
AutoConnectElement& AutoConnectAux::_loadElement(JsonObject& element, const String& name) {
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)) {
// The specified element is defined in the JSON stream.
// Loads from JSON object.
@ -1067,40 +735,43 @@ size_t AutoConnectAux::saveElement(Stream& out, std::vector<String> const& names
bufferSize += elm.getObjectSize();
break;
}
// Round up to 16 boundary
bufferSize = bufferSize > 0 ? ((bufferSize + 16) & (~0xf)) : bufferSize;
// Serialization
if (bufferSize > 0) {
DynamicJsonBuffer jb(bufferSize);
ArduinoJsonBuffer jb(bufferSize);
if (amount == 1) {
JsonObject& element = jb.createObject();
ArduinoJsonObject element = ARDUINOJSON_CREATEOBJECT(jb);
for (AutoConnectElement& elm : _addonElm)
if (elm.name.equalsIgnoreCase(names[0])) {
elm.serialize(element);
break;
}
size_n = element.printTo(out);
size_n = ARDUINOJSON_PRINT(element, out);
}
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_URI)] = _uriStr;
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) {
JsonObject& element = elements.createNestedObject();
ArduinoJsonObject element = elements.createNestedObject();
elm.serialize(element);
}
size_n = json.prettyPrintTo(out);
size_n = ARDUINOJSON_PRETTYPRINT(json, out);
}
else if (amount >= 2) {
JsonArray& elements = jb.createArray();
ArduinoJsonArray elements = ARDUINOJSON_CREATEARRAY(jb);
for (String name : names)
for (AutoConnectElement& elm : _addonElm)
if (elm.name.equalsIgnoreCase(name)) {
JsonObject& element = elements.createNestedObject();
ArduinoJsonObject element = elements.createNestedObject();
elm.serialize(element);
break;
}
size_n = elements.prettyPrintTo(out);
size_n = ARDUINOJSON_PRETTYPRINT(elements, out);
}
}
return size_n;
@ -1136,4 +807,4 @@ ACElement_t AutoConnectAux::_asElementType(const String& type) {
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 */
#ifdef AUTOCONNECT_USE_JSON
template<typename T>
bool _parseJson(T in);
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 */
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* _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 */

@ -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
#endif
#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
#define AC_UNUSED(expr) do { (void)(expr); } while (0)

@ -52,6 +52,10 @@ class AutoConnectElementBasis {
virtual ~AutoConnectElementBasis() {}
virtual const String toHTML(void) const { return value; }
ACElement_t typeOf(void) const { return _type; }
#ifndef AUTOCONNECT_USE_JSON
template<typename T>
T& as(void);
#endif
String name; /**< Element name */
String value; /**< Element value */
@ -249,4 +253,66 @@ class AutoConnectTextBasis : virtual public AutoConnectElementBasis {
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_

@ -19,6 +19,66 @@
#endif
#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
* the code held in factionf member.

@ -2,8 +2,8 @@
* Declaration of AutoConnectElement extended classes using JSON.
* @file AutoConnectElementJson.h
* @author hieromon@gmail.com
* @version 0.9.7
* @date 2018-11-17
* @version 0.9.8
* @date 2019-03-11
* @copyright MIT license.
*/
@ -45,6 +45,50 @@
#define AUTOCONNECT_JSON_VALUE_SD "sd"
#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.
* 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 bool loadMember(const JsonObject& json);
virtual void serialize(JsonObject& json);
template<typename T>
T& as(void);
protected:
void _setMember(const JsonObject& json);
@ -247,4 +293,64 @@ class AutoConnectTextJson : public AutoConnectElementJson, public AutoConnectTex
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_

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

Loading…
Cancel
Save