Fixed assign String to PROGMEM

pull/41/head
Hieromon Ikasamo 6 years ago
parent 3876ce8361
commit 7270f93868
  1. 33
      src/AutoConnect.cpp
  2. 98
      src/AutoConnectElementBasisImpl.h
  3. 13
      src/AutoConnectPage.cpp

@ -393,6 +393,7 @@ void AutoConnect::_startWebServer() {
if (!_responsePage) { if (!_responsePage) {
_responsePage = new PageBuilder(); _responsePage = new PageBuilder();
_responsePage->chunked(AUTOCONNECT_HTTP_TRANSFER); _responsePage->chunked(AUTOCONNECT_HTTP_TRANSFER);
_responsePage->reserve(AUTOCONNECT_CONTENTBUFFER_SIZE);
_responsePage->exitCanHandle(std::bind(&AutoConnect::_classifyHandle, this, std::placeholders::_1, std::placeholders::_2)); _responsePage->exitCanHandle(std::bind(&AutoConnect::_classifyHandle, this, std::placeholders::_1, std::placeholders::_2));
_responsePage->insert(*_webServer); _responsePage->insert(*_webServer);
@ -460,7 +461,7 @@ void AutoConnect::handleRequest() {
AC_DBG("%s credential saved\n", reinterpret_cast<const char*>(_credential.ssid)); AC_DBG("%s credential saved\n", reinterpret_cast<const char*>(_credential.ssid));
} }
// Ensures that keeps a connection with the current AP while the portal behaves. // Ensures that keeps a connection with the current AP while the portal behaves.
_setReconnect(AC_RECONNECT_SET); _setReconnect(AC_RECONNECT_SET);
} }
else else
@ -600,8 +601,8 @@ bool AutoConnect::_captivePortal() {
String hostHeader = _webServer->hostHeader(); String hostHeader = _webServer->hostHeader();
if (!_isIP(hostHeader) && (hostHeader != WiFi.localIP().toString())) { if (!_isIP(hostHeader) && (hostHeader != WiFi.localIP().toString())) {
String location = String(F("http://")) + _webServer->client().localIP().toString() + String(AUTOCONNECT_URI); String location = String(F("http://")) + _webServer->client().localIP().toString() + String(AUTOCONNECT_URI);
_webServer->sendHeader(F("Location"), location, true); _webServer->sendHeader(String(F("Location")), location, true);
_webServer->send(302, F("text/plain"), ""); _webServer->send(302, String(F("text/plain")), "");
_webServer->client().flush(); _webServer->client().flush();
_webServer->client().stop(); _webServer->client().stop();
return true; return true;
@ -649,13 +650,13 @@ void AutoConnect::_handleNotFound() {
_notFoundHandler(); _notFoundHandler();
} }
else { else {
PageElement page404(_PAGE_404, { { "HEAD", std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1) } }); PageElement page404(_PAGE_404, { { String(F("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1) } });
String html = page404.build(); String html = page404.build();
_webServer->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate"), true); _webServer->sendHeader(String(F("Cache-Control")), String(F("no-cache, no-store, must-revalidate")), true);
_webServer->sendHeader(F("Pragma"), F("no-cache")); _webServer->sendHeader(String(F("Pragma")), String(F("no-cache")));
_webServer->sendHeader(F("Expires"), F("-1")); _webServer->sendHeader(String(F("Expires")), String("-1"));
_webServer->sendHeader(F("Content-Length"), String(html.length())); _webServer->sendHeader(String(F("Content-Length")), String(html.length()));
_webServer->send(404, F("text/html"), html); _webServer->send(404, String(F("text/html")), html);
} }
} }
} }
@ -709,7 +710,7 @@ String AutoConnect::_induceConnect(PageArgument& args) {
_rfConnect = true; _rfConnect = true;
// Since v0.9.7, the redirect method changed from a 302 response to the // Since v0.9.7, the redirect method changed from a 302 response to the
// meta tag with refresh attribute. // meta tag with refresh attribute.
// This approach for ESP32 makes an inefficient choice. The waiting // This approach for ESP32 makes an inefficient choice. The waiting
// procedure for a connection attempt should be the server side. Also, // procedure for a connection attempt should be the server side. Also,
// the proper value of waiting time until refreshing is unknown. But // the proper value of waiting time until refreshing is unknown. But
@ -730,9 +731,8 @@ String AutoConnect::_induceConnect(PageArgument& args) {
// String url = String(F("http://")) + _webServer->client().localIP().toString() + String(AUTOCONNECT_URI_RESULT); // String url = String(F("http://")) + _webServer->client().localIP().toString() + String(AUTOCONNECT_URI_RESULT);
// _webServer->sendHeader(F("Location"), url, true); // _webServer->sendHeader(F("Location"), url, true);
// _webServer->send(302, F("text/plain"), ""); // _webServer->send(302, F("text/plain"), "");
// _webServer->client().stop();
// _webServer->client().flush(); // _webServer->client().flush();
// _waitForEndTransmission(); // Wait for response transmission complete // _webServer->client().stop();
// _responsePage->cancel(); // _responsePage->cancel();
return String(""); return String("");
} }
@ -742,10 +742,11 @@ String AutoConnect::_induceConnect(PageArgument& args) {
* A destination as _redirectURI is indicated by loop to establish connection. * A destination as _redirectURI is indicated by loop to establish connection.
*/ */
String AutoConnect::_invokeResult(PageArgument& args) { String AutoConnect::_invokeResult(PageArgument& args) {
AC_DBG("_invokeResult entered\n");
String redirect = String(F("http://")); String redirect = String(F("http://"));
// The host address to which the connection result for ESP32 responds // The host address to which the connection result for ESP32 responds
// changed from v0.9.7. This change is a measure according to the // changed from v0.9.7. This change is a measure according to the
// implementation of the arduino-esp32 1.0.1 core. // implementation of the arduino-esp32 1.0.1.
#if defined(ARDUINO_ARCH_ESP32) #if defined(ARDUINO_ARCH_ESP32)
// In ESP32, the station IP address just established could not be reached. // In ESP32, the station IP address just established could not be reached.
redirect += _webServer->client().localIP().toString(); redirect += _webServer->client().localIP().toString();
@ -756,10 +757,10 @@ String AutoConnect::_invokeResult(PageArgument& args) {
redirect += _currentHostIP.toString(); redirect += _currentHostIP.toString();
#endif #endif
redirect += _redirectURI; redirect += _redirectURI;
_webServer->sendHeader(F("Location"), redirect, true); _webServer->sendHeader(String(F("Location")), redirect, true);
_webServer->send(302, F("text/plain"), ""); _webServer->send(302, String(F("text/plain")), "");
_webServer->client().stop();
_webServer->client().flush(); _webServer->client().flush();
_webServer->client().stop();
_waitForEndTransmission(); // Wait for response transmission complete _waitForEndTransmission(); // Wait for response transmission complete
_responsePage->cancel(); _responsePage->cancel();
return String(""); return String("");

@ -18,7 +18,7 @@
* @return An HTML string. * @return An HTML string.
*/ */
const String AutoConnectButtonBasis::toHTML(void) const { const String AutoConnectButtonBasis::toHTML(void) const {
return String(FPSTR("<button type=\"button\" name=\"")) + name + String(FPSTR("\" value=\"")) + value + String(FPSTR("\" onclick=\"")) + action + String("\">") + value + String(FPSTR("</button>")); return String(F("<button type=\"button\" name=\"")) + name + String(F("\" value=\"")) + value + String(F("\" onclick=\"")) + action + String("\">") + value + String(F("</button>"));
} }
/** /**
@ -32,34 +32,34 @@ const String AutoConnectButtonBasis::toHTML(void) const {
const String AutoConnectCheckboxBasis::toHTML(void) const { const String AutoConnectCheckboxBasis::toHTML(void) const {
String html; String html;
html = String(FPSTR("<input type=\"checkbox\" name=\"")) + name + String(FPSTR("\" value=\"")) + value + String("\""); html = String(F("<input type=\"checkbox\" name=\"")) + name + String(F("\" value=\"")) + value + String("\"");
if (checked) if (checked)
html += String(FPSTR(" checked")); html += String(F(" checked"));
if (label.length()) if (label.length())
html += String(" id=\"") + name + String("\"><label for=\"") + name + String("\">") + label + String(FPSTR("</label")); html += String(F(" id=\"")) + name + String(F("\"><label for=\"")) + name + String("\">") + label + String(F("</label"));
html += String(FPSTR("><br>")); html += String(F("><br>"));
return html; return html;
} }
/** /**
* Generate an HTML <input type=text> element. * Generate an HTML <input type=text> element.
* If the value member is contained, it is reflected in the placeholder * If the value member is contained, it is reflected in the placeholder
* attribute. The entered value can be obtained using the user callback * attribute. The entered value can be obtained using the user callback
* function registered by AutoConnectAux::on after the form is sent in * function registered by AutoConnectAux::on after the form is sent in
* combination with AutoConnectSubmit. * combination with AutoConnectSubmit.
* @return String an HTML string. * @return String an HTML string.
*/ */
const String AutoConnectInputBasis::toHTML(void) const { const String AutoConnectInputBasis::toHTML(void) const {
String html = String(); String html = String("");
if (label.length()) if (label.length())
html = String(FPSTR("<label for=\"")) + name + String("\">") + label + String(FPSTR("</label>")); html = String(F("<label for=\"")) + name + String("\">") + label + String(F("</label>"));
html += String(FPSTR("<input type=\"text\" id=\"")) + name + String(FPSTR("\" name=\"")) + name + String("\""); html += String(F("<input type=\"text\" id=\"")) + name + String(F("\" name=\"")) + name + String("\"");
if (placeholder.length()) if (placeholder.length())
html += String(FPSTR(" placeholder=\"")) + placeholder + String("\""); html += String(F(" placeholder=\"")) + placeholder + String("\"");
if (value.length()) if (value.length())
html += String(FPSTR(" value=\"")) + value + String("\""); html += String(F(" value=\"")) + value + String("\"");
html += String(FPSTR("><br>")); html += String(F("><br>"));
return html; return html;
} }
@ -91,31 +91,39 @@ void AutoConnectRadioBasis::empty(const size_t reserve) {
} }
/** /**
* Generate an HTML <input type=radio> element with an <option> element. * Generate an HTML <input type=radio> element with an <option> element.
* @return String an HTML string. * @return String an HTML string.
*/ */
const String AutoConnectRadioBasis::toHTML(void) const { const String AutoConnectRadioBasis::toHTML(void) const {
String html = ""; String html = String("");
if (label.length()) { if (label.length()) {
html = label; html = label;
if (order == AC_Vertical) if (order == AC_Vertical)
html += String("<br>"); html += String(F("<br>"));
} }
uint8_t n = 0; uint8_t n = 0;
for (const String value : _values) { for (const String value : _values) {
n++; n++;
String id = name + "_" + String(n); String id = name + "_" + String(n);
html += String(FPSTR("<input type=\"radio\" name=\"")) + name + String(FPSTR("\" id=\"")) + id + String(FPSTR("\" value=\"")) + value + String("\""); html += String(F("<input type=\"radio\" name=\"")) + name + String(F("\" id=\"")) + id + String(F("\" value=\"")) + value + String("\"");
if (n == checked - 1) if (n == checked - 1)
html += String(FPSTR(" checked")); html += String(F(" checked"));
html += String(FPSTR("><label for=\"")) + id + String("\">") + value + String(FPSTR("</label>")); html += String(F("><label for=\"")) + id + String("\">") + value + String(F("</label>"));
if (order == AC_Vertical) if (order == AC_Vertical)
html += String("<br>"); html += String(F("<br>"));
} }
return html; return html;
} }
/**
* Returns current selected value in the radio same group
*/
const String& AutoConnectRadioBasis::value() const {
static const String _nullString = String();
return checked ? _values.at(checked - 1) : _nullString;
}
/** /**
* Clear option items of AutoConnectSelect and reallocate new storage. * Clear option items of AutoConnectSelect and reallocate new storage.
* All hold items are released. * All hold items are released.
@ -130,42 +138,42 @@ void AutoConnectSelectBasis::empty(const size_t reserve) {
} }
/** /**
* Generate an HTML <select> element with an <option> element. * Generate an HTML <select> element with an <option> element.
* The attribute value of the <option> element is given to the * The attribute value of the <option> element is given to the
* AutoConnectSelect class as a string array, which would be stored * AutoConnectSelect class as a string array, which would be stored
* in the 'options' member. If a label member is contained, the <label> * in the 'options' member. If a label member is contained, the <label>
* element would be generated the preface of <select>. * element would be generated the preface of <select>.
* @return String an HTML string. * @return String an HTML string.
*/ */
const String AutoConnectSelectBasis::toHTML(void) const { const String AutoConnectSelectBasis::toHTML(void) const {
String html = ""; String html = String("");
if (label.length()) if (label.length())
html = String(FPSTR("<label for=\"")) + name + String("\">") + label + String(FPSTR("</label>")); html = String(F("<label for=\"")) + name + String("\">") + label + String(F("</label>"));
html += String(FPSTR("<select name=\"")) + name + String("\" id=\"") + name + String("\">"); html += String(F("<select name=\"")) + name + String(F("\" id=\"")) + name + String("\">");
for (const String option : _options) for (const String option : _options)
html += String(FPSTR("<option value=\"")) + option + "\">" + option + String(FPSTR("</option>")); html += String(F("<option value=\"")) + option + "\">" + option + String(F("</option>"));
html += String(FPSTR("</select>")); html += String(F("</select>"));
return html; return html;
} }
/** /**
* Generate an HTML <input type=button> element. This element is used * Generate an HTML <input type=button> element. This element is used
* for form submission. An 'onclick' attribute calls fixed JavaScript * for form submission. An 'onclick' attribute calls fixed JavaScript
* code as 'sa' named and it's included in the template. * code as 'sa' named and it's included in the template.
* @return String an HTML string. * @return String an HTML string.
*/ */
const String AutoConnectSubmitBasis::toHTML(void) const { const String AutoConnectSubmitBasis::toHTML(void) const {
return String(FPSTR("<input type=\"button\" name=\"")) + name + String(FPSTR("\" value=\"")) + value + String(FPSTR("\" onclick=\"_sa('")) + uri + String("')\">"); return String(F("<input type=\"button\" name=\"")) + name + String(F("\" value=\"")) + value + String(F("\" onclick=\"_sa('")) + uri + String("')\">");
} }
/** /**
* Generate an HTML text element from a string of the value member. If a style * Generate an HTML text element from a string of the value member. If a style
* exists, it gives a style attribute. * exists, it gives a style attribute.
* @return String an HTML string. * @return String an HTML string.
*/ */
const String AutoConnectTextBasis::toHTML(void) const { const String AutoConnectTextBasis::toHTML(void) const {
return String(FPSTR("<div style=\"")) + style + String("\">") + value + String(FPSTR("</div>")); return String(F("<div style=\"")) + style + String("\">") + value + String(F("</div>"));
} }
#endif // _AUTOCONNECTELEMENTBASISIMPL_H_ #endif // _AUTOCONNECTELEMENTBASISIMPL_H_

@ -711,7 +711,7 @@ const char AutoConnect::_PAGE_OPENCREDT[] PROGMEM = {
const char AutoConnect::_PAGE_CONNECTING[] PROGMEM = { const char AutoConnect::_PAGE_CONNECTING[] PROGMEM = {
"{{REQ}}" "{{REQ}}"
"{{HEAD}}" "{{HEAD}}"
"<meta http-equiv=\"refresh\" content=\"0;url=" AUTOCONNECT_URI_RESULT "\">" "<meta http-equiv=\"refresh\" content=\"1;url=" AUTOCONNECT_URI_RESULT "\">"
"<title>AutoConnect connecting</title>" "<title>AutoConnect connecting</title>"
"<style type=\"text/css\">" "<style type=\"text/css\">"
"{{CSS_BASE}}" "{{CSS_BASE}}"
@ -729,13 +729,13 @@ const char AutoConnect::_PAGE_CONNECTING[] PROGMEM = {
"{{MENU_PRE}}" "{{MENU_PRE}}"
"{{MENU_POST}}" "{{MENU_POST}}"
"<div class=\"spinner\">" "<div class=\"spinner\">"
"<div style=\"position:absolute;left:-100%;right:-100%;text-align:center;margin:10px auto;font-weight:bold;color:#4169e1;\">{{CUR_SSID}}</div>"
"<div class=\"double-bounce1\"></div>" "<div class=\"double-bounce1\"></div>"
"<div class=\"double-bounce2\"></div>" "<div class=\"double-bounce2\"></div>"
"<div style=\"position:absolute;left:-100%;right:-100%;text-align:center;margin:10px auto;font-weight:bold;color:#4169e1;\">{{CUR_SSID}}</div>"
"</div>" "</div>"
"</div>" "</div>"
"</body>" "</body>"
"</html>" "</html>"
}; };
/**< A page announcing that a connection has been established. */ /**< A page announcing that a connection has been established. */
@ -1025,7 +1025,7 @@ String AutoConnect::_token_STATION_STATUS(PageArgument& args) {
wlStatusSymbol = wlStatusSymbols[7]; wlStatusSymbol = wlStatusSymbols[7];
#endif #endif
} }
return "(" + String(_rsConnect) + ") " + String(wlStatusSymbol); return String("(") + String(_rsConnect) + String(") ") + String(wlStatusSymbol);
} }
String AutoConnect::_token_LOCAL_IP(PageArgument& args) { String AutoConnect::_token_LOCAL_IP(PageArgument& args) {
@ -1090,7 +1090,7 @@ String AutoConnect::_token_CHIP_ID(PageArgument& args) {
String AutoConnect::_token_FREE_HEAP(PageArgument& args) { String AutoConnect::_token_FREE_HEAP(PageArgument& args) {
AC_UNUSED(args); AC_UNUSED(args);
return String(ESP.getFreeHeap()); return String(_freeHeapSize);
} }
String AutoConnect::_token_LIST_SSID(PageArgument& args) { String AutoConnect::_token_LIST_SSID(PageArgument& args) {
@ -1103,7 +1103,7 @@ String AutoConnect::_token_LIST_SSID(PageArgument& args) {
for (uint8_t i = 0; i < nn; i++) { for (uint8_t i = 0; i < nn; i++) {
String ssid = WiFi.SSID(i); String ssid = WiFi.SSID(i);
if (ssid.length() > 0) { if (ssid.length() > 0) {
ssidList += String(F("<input type=\"button\" onClick=\"document.getElementById('ssid').value=this.getAttribute('value');document.getElementById('passphrase').focus()\" value=\"")) + ssid + String(F("\">")); ssidList += String(F("<input type=\"button\" onClick=\"document.getElementById('ssid').value=this.getAttribute('value');document.getElementById('passphrase').focus()\" value=\"")) + ssid + String("\">");
ssidList += String(F("<label>")) + String(AutoConnect::_toWiFiQuality(WiFi.RSSI(i))) + String(F("&#037;</label>")); ssidList += String(F("<label>")) + String(AutoConnect::_toWiFiQuality(WiFi.RSSI(i))) + String(F("&#037;</label>"));
if (WiFi.encryptionType(i) != ENC_TYPE_NONE) if (WiFi.encryptionType(i) != ENC_TYPE_NONE)
ssidList += String(F("<span class=\"img-lock\"></span>")); ssidList += String(F("<span class=\"img-lock\"></span>"));
@ -1192,6 +1192,7 @@ PageElement* AutoConnect::_setupPage(String uri) {
if (uri == String(AUTOCONNECT_URI)) { if (uri == String(AUTOCONNECT_URI)) {
// Setup /auto // Setup /auto
_freeHeapSize = ESP.getFreeHeap();
elm->setMold(_PAGE_STAT); elm->setMold(_PAGE_STAT);
elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1));
elm->addToken(String(FPSTR("CSS_BASE")), std::bind(&AutoConnect::_token_CSS_BASE, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_BASE")), std::bind(&AutoConnect::_token_CSS_BASE, this, std::placeholders::_1));

Loading…
Cancel
Save