表示するものがひとつもありません。setStoreTitle関数を使って表示をするか、WriteModeにしてください。");
}
@@ -64,32 +63,59 @@ String Nefry_Conf::beginWeb(String link) {
content += F("
");
if (Nefry.getWriteMode())content += "WriteMode";
content += F("
Back to top");
- return NefryWeb.createHtml(F("Nefry DataStore"), "", content);
- }
- return "";
+ NefryWebServer.getWebServer()->send(200, "text/html", NefryWeb.createHtml(F("Nefry DataStore"), "", content));
+ });
+
+ NefryWebServer.getWebServer()->on("/set_config", [&]() {
+ char webarg[5] = { "smo0" };
+ for (int i = 0; i < 10; i++) {
+ webarg[3] = '0' + i;
+ String s = NefryWebServer.getWebServer()->arg(webarg);
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print(webarg);
+ DEBUG_OUTPUT.print(" : ");
+ DEBUG_OUTPUT.println(s);
+#endif
+ NefryDataStore.setStorageStr(s, i);
+ }
+ webarg[0] = 'i';
+ for (int i = 0; i < 10; i++) {
+ webarg[3] = '0' + i;
+ String s = NefryWebServer.getWebServer()->arg(webarg);
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print(webarg);
+ DEBUG_OUTPUT.print(" : ");
+ DEBUG_OUTPUT.println(s);
+#endif
+ NefryDataStore.setStorageValue(s.toInt(), i);
+ }
+ NefryWebServer.getWebServer()->send(200, "text/html", NefryWeb.createHtml(F("Nefry DataStore Set"), "", F("
Nefry Module Set
Saveing & Restart...
Back to top")));
+ NefryWebServer.resetTimer(2);
+ });
}
- /* HTMLに表示するのか */
+/* HTMLに表示するのか */
void Nefry_Conf::setStoreTitle(const char set[15], const int num) {
if (0 <= num&&num < 20) {
strcpy(module_input[num], set);
- htmlPrint[num] = 1;
+ htmlPrint[num] = true;
}
}
+
void Nefry_Conf::begin()
{
for (int i = 0; i < 10; i++) {
sprintf(module_input[i], "String %d", i);
- sprintf(module_input[10+i], "Value %d", 10+i);
+ sprintf(module_input[10 + i], "Value %d", 10 + i);
if (Nefry.getWriteMode()) {
- htmlPrint[i] = 1;
- htmlPrint[10+i] = 1;
+ htmlPrint[i] = true;
+ htmlPrint[10 + i] = true;
}
else {
- htmlPrint[i] = 0;
- htmlPrint[10 + i] = 0;
- }
+ htmlPrint[i] = false;
+ htmlPrint[10 + i] = false;
+ }
}
}
Nefry_Conf NefryConfig;
\ No newline at end of file
diff --git a/cores/esp32/nefry/NefryConfig.h b/cores/esp32/nefry/NefryConfig.h
index 66250e5b563..375f70f6378 100644
--- a/cores/esp32/nefry/NefryConfig.h
+++ b/cores/esp32/nefry/NefryConfig.h
@@ -9,13 +9,9 @@ class Nefry_Conf
{
public:
void
+ beginWeb(),
begin(),
setStoreTitle(const char set[15], const int num);
-
- String
- beginWeb(String link),
- setDefaultModuleId();
-
private:
bool htmlPrint[20];//10
char module_input[20][15];
diff --git a/cores/esp32/nefry/NefryWeb.cpp b/cores/esp32/nefry/NefryWeb.cpp
index b5c00da5de4..1669000a614 100644
--- a/cores/esp32/nefry/NefryWeb.cpp
+++ b/cores/esp32/nefry/NefryWeb.cpp
@@ -7,10 +7,10 @@ This software is released under the MIT License.
http://opensource.org/licenses/mit-license.php
*/
-
-#include "NefryWeb.h"
+#include "./NefryWeb.h"
//web
-/*
+String indexlink;
+
void Nefry_Web::setIndexLink(const char title[32], const char url[32])
{
indexlink += "
0) {
- NefryWiFi.addWifi(newssid, newpwd);
- NefryWiFi.saveWifi();
- content = F("Save SSID:");
- content += newssid;
- content += F(" Restart to boot into new WiFi");
- }
- else {
- content = F("Empty SSID is not acceptable.");
- }
- send(200, "text/html", NefryWeb.createHtml(F("Nefry Wifi Set"), "", (String)F("Nefry Wifi Set
") + content + (String)F("
Back to top")));
- Serial.print("dateSend");
- if (newssid.length() != 0)resetTimer(2);
- }
- else if (url.equalsIgnoreCase("/delete_wifi")) {
- String del = "",ssid;
- deleteFlg = false;
- for (int i = 0; i < _currentArgCount; i++) {
- ssid = NefryWiFi.deleteWifi(_currentArgs[i].key.toInt());
- if (!ssid.equals("")) {
- del += "";
- del += ssid;
- del += "";
- deleteFlg = true;
- }
- }
- NefryWiFi.saveWifi();
- send(200, "text/html", NefryWeb.createHtml(F("Nefry Wifi Delete"), "", (String)F("
Nefry Wifi Delete
Delete List
Back to top")));
- if (deleteFlg ==true)resetTimer(2);
- }
- else if (url.equalsIgnoreCase("/config")) {
- send(200, "text/html", NefryConfig.beginWeb("config"));
- }
- else if (url.equalsIgnoreCase("/set_config")) {
- char webarg[5] = { "smo0" };
- for (int i = 0; i < 10; i++) {
- webarg[3] = '0' + i;
- String s = arg(webarg);
-#ifdef DEBUG_ESP_HTTP_SERVER
- DEBUG_OUTPUT.print(webarg);
- DEBUG_OUTPUT.print(" : ");
- DEBUG_OUTPUT.println(s);
-#endif
- NefryDataStore.setStorageStr(s,i);
- }
- webarg[0] = 'i';
- for (int i = 0; i < 10; i++) {
- webarg[3] = '0' + i;
- String s = arg(webarg);
-#ifdef DEBUG_ESP_HTTP_SERVER
- DEBUG_OUTPUT.print(webarg);
- DEBUG_OUTPUT.print(" : ");
- DEBUG_OUTPUT.println(s);
-#endif
- NefryDataStore.setStorageValue(s.toInt(),i);
- }
- resetTimer(2);
- send(200, "text/html", NefryWeb.createHtml(F("Nefry DataStore Set"), "", F("
Nefry Module Set
Saveing & Restart...
Back to top")));
- resetTimer(2);
- }
- /* "/"は必ず一番下にすること */
- else if (url.equalsIgnoreCase("/")) {
- send(200, "text/html", NefryWeb.beginWeb("index"));
- }
- else {
- send(404, "text/html", NefryWeb.beginWeb("NotFound"));
- }
- _currentClient.flush();
- _currentClient = WiFiClient();
-}
-
-void Nefry_webserver::sendHeader(const String& name, const String& value, bool first) {
- String headerLine = name;
- headerLine += ": ";
- headerLine += value;
- headerLine += "\r\n";
-
- if (first) {
- _responseHeaders = headerLine + _responseHeaders;
- }
- else {
- _responseHeaders += headerLine;
- }
-}
-void Nefry_webserver::_prepareHeader(String& response, int code, const char* content_type, size_t contentLength) {
- response = "HTTP/1.1 ";
- response += String(code);
- response += " ";
- response += _responseCodeToString(code);
- response += "\r\n";
-
- if (!content_type)
- content_type = "text/html";
-
- sendHeader("Content-Type", content_type, true);
- sendHeader("Content-Length", String(contentLength));
- sendHeader("Connection", "close");
- sendHeader("Access-Control-Allow-Origin", "*");
-
- response += _responseHeaders;
- response += "\r\n";
- _responseHeaders = String();
-}
-void Nefry_webserver::send(int code, const char* content_type, const String& content) {
- String header;
- _prepareHeader(header, code, content_type, content.length());
- sendContent(header);
- sendContent(content);
-}
-void Nefry_webserver::sendContent(const String& content) {
- const size_t unit_size = HTTP_DOWNLOAD_UNIT_SIZE;
- size_t size_to_send = content.length();
- const char* send_start = content.c_str();
-
- while (size_to_send) {
- size_t will_send = (size_to_send < unit_size) ? size_to_send : unit_size;
- size_t sent = _currentClient.write(send_start, will_send);
- if (sent == 0) {
- break;
- }
- size_to_send -= sent;
- send_start += sent;
- }
}
-String Nefry_webserver::_responseCodeToString(int code) {
- switch (code) {
- case 100: return F("Continue");
- case 101: return F("Switching Protocols");
- case 200: return F("OK");
- case 201: return F("Created");
- case 202: return F("Accepted");
- case 203: return F("Non-Authoritative Information");
- case 204: return F("No Content");
- case 205: return F("Reset Content");
- case 206: return F("Partial Content");
- case 300: return F("Multiple Choices");
- case 301: return F("Moved Permanently");
- case 302: return F("Found");
- case 303: return F("See Other");
- case 304: return F("Not Modified");
- case 305: return F("Use Proxy");
- case 307: return F("Temporary Redirect");
- case 400: return F("Bad Request");
- case 401: return F("Unauthorized");
- case 402: return F("Payment Required");
- case 403: return F("Forbidden");
- case 404: return F("Not Found");
- case 405: return F("Method Not Allowed");
- case 406: return F("Not Acceptable");
- case 407: return F("Proxy Authentication Required");
- case 408: return F("Request Time-out");
- case 409: return F("Conflict");
- case 410: return F("Gone");
- case 411: return F("Length Required");
- case 412: return F("Precondition Failed");
- case 413: return F("Request Entity Too Large");
- case 414: return F("Request-URI Too Large");
- case 415: return F("Unsupported Media Type");
- case 416: return F("Requested range not satisfiable");
- case 417: return F("Expectation Failed");
- case 500: return F("Internal Server Error");
- case 501: return F("Not Implemented");
- case 502: return F("Bad Gateway");
- case 503: return F("Service Unavailable");
- case 504: return F("Gateway Time-out");
- case 505: return F("HTTP Version not supported");
- default: return "";
- }
-}
-
-void Nefry_webserver::_parseArguments(String data) {
- if (_currentArgs)
- delete[] _currentArgs;
- _currentArgCount = 0;
-#ifdef DEBUG_ESP_HTTP_SERVER
- DEBUG_OUTPUT.print("args: ");
- DEBUG_OUTPUT.println(data);
-#endif
- if (data.length() == 0)return;
- _currentArgCount = 1;
- for (int i = 0; i < (int)data.length(); ) {
- i = data.indexOf('&', i);
- if (i == -1)
- break;
- ++i;
- ++_currentArgCount;
- }
-#ifdef DEBUG_ESP_HTTP_SERVER
- DEBUG_OUTPUT.print("args count: ");
- DEBUG_OUTPUT.println(_currentArgCount);
-#endif
-
- _currentArgs = new RequestArgument[_currentArgCount];
- int pos = 0;
- int iarg;
- for (iarg = 0; iarg < _currentArgCount;) {
- int equal_sign_index = data.indexOf('=', pos);
- int next_arg_index = data.indexOf('&', pos);
-#ifdef DEBUG_ESP_HTTP_SERVER
- DEBUG_OUTPUT.print("pos ");
- DEBUG_OUTPUT.print(pos);
- DEBUG_OUTPUT.print("=@ ");
- DEBUG_OUTPUT.print(equal_sign_index);
- DEBUG_OUTPUT.print(" &@ ");
- DEBUG_OUTPUT.println(next_arg_index);
-#endif
- if ((equal_sign_index == -1) || ((equal_sign_index > next_arg_index) && (next_arg_index != -1))) {
-#ifdef DEBUG_ESP_HTTP_SERVER
- DEBUG_OUTPUT.print("arg missing value: ");
- DEBUG_OUTPUT.println(iarg);
-#endif
- if (next_arg_index == -1)
- break;
- pos = next_arg_index + 1;
- continue;
- }
- _currentArgs[iarg].key = data.substring(pos, equal_sign_index);
- _currentArgs[iarg].value = escapeParameter(data.substring(equal_sign_index + 1, next_arg_index));
-#ifdef DEBUG_ESP_HTTP_SERVER
- DEBUG_OUTPUT.print("arg ");
- DEBUG_OUTPUT.print(iarg);
- DEBUG_OUTPUT.print(" key: ");
- DEBUG_OUTPUT.print(_currentArgs[iarg].key);
- DEBUG_OUTPUT.print(" value: ");
- DEBUG_OUTPUT.println(_currentArgs[iarg].value);
-#endif
- ++iarg;
- if (next_arg_index == -1)
- break;
- pos = next_arg_index + 1;
- }
- _currentArgCount = iarg;
-#ifdef DEBUG_ESP_HTTP_SERVER
- DEBUG_OUTPUT.print("args count: ");
- DEBUG_OUTPUT.println(_currentArgCount);
-#endif
-
-}
-String Nefry_webserver::arg(String name) {
- for (int i = 0; i < _currentArgCount; ++i) {
- if (_currentArgs[i].key.equals(name))
- return _currentArgs[i].value;
- }
- return String();
+ESP32WebServer* Nefry_webserver::getWebServer()
+{
+ return &_nefryWebServer;
}
String Nefry_webserver::escapeParameter(String param) {
param.replace("+", " ");
@@ -366,5 +68,4 @@ String Nefry_webserver::escapeParameter(String param) {
return param;
}
-
Nefry_webserver NefryWebServer;
\ No newline at end of file
diff --git a/cores/esp32/nefry/NefryWebServer.h b/cores/esp32/nefry/NefryWebServer.h
index b37b2aa33c7..9279bbbdc8c 100644
--- a/cores/esp32/nefry/NefryWebServer.h
+++ b/cores/esp32/nefry/NefryWebServer.h
@@ -2,24 +2,10 @@
#define NefryWebServer_h
#include "./inc/WiFi/src/WiFi.h"
+#include "./inc/DNSServer/src/DNSServer.h"
#include
-
+#include "./inc/ESP32WebServer/src/ESP32WebServer.h"
#include "Nefry.h"
-#include "NefryWeb.h"
-#include "NefryWiFi.h"
-#include "NefryConfig.h"
-
-#define HTTP_DOWNLOAD_UNIT_SIZE 1460
-#define HTTP_UPLOAD_BUFLEN 2048
-#define HTTP_MAX_DATA_WAIT 1000 //ms to wait for the client to send the request
-#define HTTP_MAX_POST_WAIT 1000 //ms to wait for POST data to arrive
-#define HTTP_MAX_CLOSE_WAIT 2000 //ms to wait for the client to close the connection
-
-#define CONTENT_LENGTH_UNKNOWN ((size_t) -1)
-#define CONTENT_LENGTH_NOT_SET ((size_t) -2)
-
-#define DEBUG_OUTPUT Serial
-//#define DEBUG_ESP_HTTP_SERVERR
class Nefry_webserver
{
@@ -28,28 +14,11 @@ class Nefry_webserver
begin(),
run(),
resetTimer(int delaySec);
- String arg(String name);
+ ESP32WebServer* getWebServer();
+ String escapeParameter(String param);
private:
- WiFiServer _server;
- WiFiClient _currentClient;
- String _responseHeaders;
- size_t _contentLength;
bool resetFlg;
int countdown;
- void
- sendHeader(const String& name, const String& value, bool first = false),
- _prepareHeader(String& response, int code, const char* content_type, size_t contentLength),
- send(int code, const char* content_type, const String& content),
- sendContent(const String& content);
- String escapeParameter(String param);
- String _responseCodeToString(int code);
- void _parseArguments(String data);
- struct RequestArgument {
- String key;
- String value;
- };
- int _currentArgCount;
- RequestArgument* _currentArgs;
};
extern Nefry_webserver NefryWebServer;
#endif
diff --git a/cores/esp32/nefry/NefryWiFi.cpp b/cores/esp32/nefry/NefryWiFi.cpp
index acf27dba6c3..dfa1975eba0 100644
--- a/cores/esp32/nefry/NefryWiFi.cpp
+++ b/cores/esp32/nefry/NefryWiFi.cpp
@@ -15,7 +15,7 @@ ConnectPass : Nefryが接続するWiFiのパスワードを保存するときに
#include "NefryWiFi.h"
bool initflgWifi = false;
-void Nefry_WiFi::begin() {
+void Nefry_WiFi::begin() {
WiFi.persistent(false);
WiFi.mode(WIFI_AP_STA);
wifiMulti = WiFiMulti();
@@ -44,8 +44,10 @@ void Nefry_WiFi::begin() {
Nefry.setLed(200, 0, 0);
}
scanWiFi(); //WiFiを検索し、Webページに表示する
+ if (NefryDataStore.getModuleID().equals(""))
+ NefryDataStore.setModuleID(getDefaultModuleId());
/* Nefryが発信するWiFiの設定*/
- if ( Nefry.getWriteMode() || NefryDataStore.getModulePass().length() == 0) {
+ if (Nefry.getWriteMode() || NefryDataStore.getModulePass().length() == 0) {
WiFi.softAP(NefryDataStore.getModuleID().c_str());
Serial.println(F("\nWaiting for WiFi to connect"));
}
@@ -75,7 +77,7 @@ run関数で返す値
*/
if (initflgWifi == false)return 1;
if (getWifiTimeout() == -1)return 1;
- if (getWifiTimeout() !=0 && getWifiTimeout() <= _WifiTimeOutCount)return 2;
+ if (getWifiTimeout() != 0 && getWifiTimeout() <= _WifiTimeOutCount)return 2;
uint8_t wifiStatus = wifiMulti.run();
if (prevWifiStatus != wifiStatus) {
prevWifiStatus = wifiStatus;
@@ -129,9 +131,9 @@ run関数で返す値
return -1;
}
-String Nefry_WiFi::beginWeb(String url)
+void Nefry_WiFi::beginWeb()
{
- if (url.equals("wifi_conf")) {
+ NefryWebServer.getWebServer()->on("/wifi_conf", [&]() {
String content = F(
"Nefry Wifi Set
"
"Saved WiFi List
Delete WiFi Select
");
- return NefryWeb.createHtml(F("Nefry Wifi Confing"), "", content);
- }
- else if (url.equals("wifiReload")) {
+ NefryWebServer.getWebServer()->send(200, "text/html", NefryWeb.createHtml(F("Nefry Wifi Confing"), "", content));
+ });
+
+ NefryWebServer.getWebServer()->on("/wifiReload", [&]() {
scanWiFi();
- return NefryWeb.createHtml(F("Wifi Reload"),(String)F("
"), F("
Please wait...
"));
- }
- else if (url.equals("wifiCount")) {
+ NefryWebServer.getWebServer()->send(200, "text/html", NefryWeb.createHtml(F("Wifi Reload"),
+ (String)F(""),
+ F("Please wait...
")));
+ });
+
+ NefryWebServer.getWebServer()->on("/wifiCount", [&]() {
setWifiTimeoutClear();
- return NefryWeb.createHtml(F("Wifi Count Clear"), (String)F(""), F("Please wait...
"));
- }
- return "";
+ NefryWebServer.getWebServer()->send(200, "text/html", NefryWeb.createHtml(F("Wifi Count Clear"), (String)F(""), F("Please wait...
")));
+ });
+
+ NefryWebServer.getWebServer()->on("/set_wifi", [&]() {
+ String newssid = NefryWebServer.getWebServer()->arg("ssid");
+ String newpwd = NefryWebServer.getWebServer()->arg("pwd");
+ Serial.print("newssid : ");
+ Serial.println(newssid);
+ String content;
+ if (newssid.length() > 0) {
+ NefryWiFi.addWifi(newssid, newpwd);
+ NefryWiFi.saveWifi();
+ content = F("Save SSID:");
+ content += newssid;
+ content += F(" Restart to boot into new WiFi");
+ }
+ else {
+ content = F("Empty SSID is not acceptable.");
+ }
+ NefryWebServer.getWebServer()->send(200, "text/html", NefryWeb.createHtml(F("Nefry Wifi Set"), "", (String)F("Nefry Wifi Set
") + content + (String)F("
Back to top")));
+ Serial.print("dateSend");
+ if (newssid.length() != 0)NefryWebServer.resetTimer(2);
+ });
+
+ NefryWebServer.getWebServer()->on("/delete_wifi", [&]() {
+ String del = "", ssid;
+ bool deleteFlg = false;
+ for (int i = 0; i < 5; i++) {
+ String data = NefryWebServer.getWebServer()->arg(i);
+ if (data.equals("1")) {
+ ssid = NefryWiFi.deleteWifi(i);
+ if (!ssid.equals("")) {
+ del += "
";
+ del += ssid;
+ del += "";
+ deleteFlg = true;
+ }
+ }
+ }
+ NefryWiFi.saveWifi();
+ NefryWebServer.getWebServer()->send(200, "text/html", NefryWeb.createHtml(F("Nefry Wifi Delete"), "", (String)F("
Nefry Wifi Delete
Delete List
Back to top")));
+ if (deleteFlg == true)NefryWebServer.resetTimer(2);
+ });
}
@@ -177,7 +223,7 @@ String Nefry_WiFi::deleteWifi(int id)
if (id < 0 || id >= 5)return "";
String ssid = _nefryssid[id];
_nefryssid[id] = "";
- _nefrypwd[id]="";
+ _nefrypwd[id] = "";
return ssid;
}
@@ -187,14 +233,14 @@ void Nefry_WiFi::addWifi(String _ssid, String _pwd)
for (int i = 0; i < 5; i++) {
if (_nefryssid[i].equals("")) {
_nefryssid[i] = _ssid;
- _nefrypwd[i]=_pwd;
+ _nefrypwd[i] = _pwd;
return;
}
}
deleteWifi(0);
sortWifi();
- _nefryssid[4]=_ssid;
- _nefrypwd[4]=_pwd;
+ _nefryssid[4] = _ssid;
+ _nefrypwd[4] = _pwd;
}
int Nefry_WiFi::sortWifi()
{
@@ -217,19 +263,19 @@ int Nefry_WiFi::sortWifi()
void Nefry_WiFi::saveWifi() {
sortWifi();
for (int i = 0; i < 5; i++) {
- NefryDataStore.setConnectSSID(_nefryssid[i],i);
- NefryDataStore.setConnectPass(_nefrypwd[i],i);
+ NefryDataStore.setConnectSSID(_nefryssid[i], i);
+ NefryDataStore.setConnectPass(_nefrypwd[i], i);
}
}
String Nefry_WiFi::getlistWifi() {
String lisWifi = "";
for (int i = 0; i < 5; i++) {
if (!_nefryssid[i].equals("")) {
- lisWifi += "ID : ";
- lisWifi += i;
- lisWifi += " SSID : ";
- lisWifi += _nefryssid[i];
- lisWifi += "\n";
+ lisWifi += "ID : ";
+ lisWifi += i;
+ lisWifi += " SSID : ";
+ lisWifi += _nefryssid[i];
+ lisWifi += "\n";
}
}
return lisWifi;
@@ -276,7 +322,7 @@ void Nefry_WiFi::dataCache()
_nefryssid[i] = NefryDataStore.getConnectSSID(i);
_nefrypwd[i] = NefryDataStore.getConnectPass(i);
}
-
+
}
/* 文字置換 */
String Nefry_WiFi::escapeParameter(String param) {
@@ -327,4 +373,20 @@ void Nefry_WiFi::setWifiTimeoutClear()
_WifiTimeOutCount = 0;
}
+String Nefry_WiFi::getDefaultModuleId() {
+ uint8_t macAddr[6];
+ char str[15];
+ char* moduleName;
+ WiFi.macAddress(macAddr);
+ switch (boardId)
+ {
+ case 0:case 1:
+ moduleName = "Nefry";
+ break;
+ }
+ sprintf(str, "%s-%02x%02x", moduleName, macAddr[6 - 2], macAddr[6 - 1]);
+ Serial.println(str);
+ return str;
+}
+
Nefry_WiFi NefryWiFi;
\ No newline at end of file
diff --git a/cores/esp32/nefry/NefryWiFi.h b/cores/esp32/nefry/NefryWiFi.h
index e8d2b7226a1..8e2f7d84195 100644
--- a/cores/esp32/nefry/NefryWiFi.h
+++ b/cores/esp32/nefry/NefryWiFi.h
@@ -4,7 +4,7 @@
#include "./inc/WiFi/src/WiFiMulti.h"
#include "Nefry.h"
#include "./inc/Preferences/src/Preferences.h"
-#include"NefryWeb.h"
+#include "NefryWeb.h"
#include "NefryWebServer.h"
class Nefry_WiFi
@@ -12,16 +12,19 @@ class Nefry_WiFi
public:
void
begin(),
+ beginWeb(),
addWifi(String ssid, String pwd),
setWifiTimeout(int count),
setWifiTimeoutClear(),
saveWifi();
+ String getDefaultModuleId();
+
int
run(),
getWifiTimeout();
- String beginWeb(String s),
+ String
deleteWifi(int id),
getlistWifi();
diff --git a/cores/esp32/nefry/inc/DNSServer/examples/CaptivePortal/CaptivePortal.ino b/cores/esp32/nefry/inc/DNSServer/examples/CaptivePortal/CaptivePortal.ino
new file mode 100644
index 00000000000..eb22782205d
--- /dev/null
+++ b/cores/esp32/nefry/inc/DNSServer/examples/CaptivePortal/CaptivePortal.ino
@@ -0,0 +1,34 @@
+#include
+#include
+#include
+
+const byte DNS_PORT = 53;
+IPAddress apIP(192, 168, 1, 1);
+DNSServer dnsServer;
+ESP8266WebServer webServer(80);
+
+String responseHTML = ""
+ "CaptivePortal"
+ "Hello World!
This is a captive portal example. All requests will "
+ "be redirected here.
";
+
+void setup() {
+ WiFi.mode(WIFI_AP);
+ WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
+ WiFi.softAP("DNSServer CaptivePortal example");
+
+ // if DNSServer is started with "*" for domain name, it will reply with
+ // provided IP to all DNS request
+ dnsServer.start(DNS_PORT, "*", apIP);
+
+ // replay to all requests with same HTML
+ webServer.onNotFound([]() {
+ webServer.send(200, "text/html", responseHTML);
+ });
+ webServer.begin();
+}
+
+void loop() {
+ dnsServer.processNextRequest();
+ webServer.handleClient();
+}
diff --git a/cores/esp32/nefry/inc/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino b/cores/esp32/nefry/inc/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino
new file mode 100644
index 00000000000..229662651e6
--- /dev/null
+++ b/cores/esp32/nefry/inc/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino
@@ -0,0 +1,135 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+/*
+ * This example serves a "hello world" on a WLAN and a SoftAP at the same time.
+ * The SoftAP allow you to configure WLAN parameters at run time. They are not setup in the sketch but saved on EEPROM.
+ *
+ * Connect your computer or cell phone to wifi network ESP_ap with password 12345678. A popup may appear and it allow you to go to WLAN config. If it does not then navigate to http://192.168.4.1/wifi and config it there.
+ * Then wait for the module to connect to your wifi and take note of the WLAN IP it got. Then you can disconnect from ESP_ap and return to your regular WLAN.
+ *
+ * Now the ESP8266 is in your network. You can reach it through http://192.168.x.x/ (the IP you took note of) or maybe at http://esp8266.local too.
+ *
+ * This is a captive portal because through the softAP it will redirect any http request to http://192.168.4.1/
+ */
+
+/* Set these to your desired softAP credentials. They are not configurable at runtime */
+const char *softAP_ssid = "ESP_ap";
+const char *softAP_password = "12345678";
+
+/* hostname for mDNS. Should work at least on windows. Try http://esp8266.local */
+const char *myHostname = "esp8266";
+
+/* Don't set this wifi credentials. They are configurated at runtime and stored on EEPROM */
+char ssid[32] = "";
+char password[32] = "";
+
+// DNS server
+const byte DNS_PORT = 53;
+DNSServer dnsServer;
+
+// Web server
+ESP8266WebServer server(80);
+
+/* Soft AP network parameters */
+IPAddress apIP(192, 168, 4, 1);
+IPAddress netMsk(255, 255, 255, 0);
+
+
+/** Should I connect to WLAN asap? */
+boolean connect;
+
+/** Last time I tried to connect to WLAN */
+long lastConnectTry = 0;
+
+/** Current WLAN status */
+int status = WL_IDLE_STATUS;
+
+void setup() {
+ delay(1000);
+ Serial.begin(9600);
+ Serial.println();
+ Serial.print("Configuring access point...");
+ /* You can remove the password parameter if you want the AP to be open. */
+ WiFi.softAPConfig(apIP, apIP, netMsk);
+ WiFi.softAP(softAP_ssid, softAP_password);
+ delay(500); // Without delay I've seen the IP address blank
+ Serial.print("AP IP address: ");
+ Serial.println(WiFi.softAPIP());
+
+ /* Setup the DNS server redirecting all the domains to the apIP */
+ dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
+ dnsServer.start(DNS_PORT, "*", apIP);
+
+ /* Setup web pages: root, wifi config pages, SO captive portal detectors and not found. */
+ server.on("/", handleRoot);
+ server.on("/wifi", handleWifi);
+ server.on("/wifisave", handleWifiSave);
+ server.on("/generate_204", handleRoot); //Android captive portal. Maybe not needed. Might be handled by notFound handler.
+ server.on("/fwlink", handleRoot); //Microsoft captive portal. Maybe not needed. Might be handled by notFound handler.
+ server.onNotFound ( handleNotFound );
+ server.begin(); // Web server start
+ Serial.println("HTTP server started");
+ loadCredentials(); // Load WLAN credentials from network
+ connect = strlen(ssid) > 0; // Request WLAN connect if there is a SSID
+}
+
+void connectWifi() {
+ Serial.println("Connecting as wifi client...");
+ WiFi.disconnect();
+ WiFi.begin ( ssid, password );
+ int connRes = WiFi.waitForConnectResult();
+ Serial.print ( "connRes: " );
+ Serial.println ( connRes );
+}
+
+void loop() {
+ if (connect) {
+ Serial.println ( "Connect requested" );
+ connect = false;
+ connectWifi();
+ lastConnectTry = millis();
+ }
+ {
+ int s = WiFi.status();
+ if (s == 0 && millis() > (lastConnectTry + 60000) ) {
+ /* If WLAN disconnected and idle try to connect */
+ /* Don't set retry time too low as retry interfere the softAP operation */
+ connect = true;
+ }
+ if (status != s) { // WLAN status change
+ Serial.print ( "Status: " );
+ Serial.println ( s );
+ status = s;
+ if (s == WL_CONNECTED) {
+ /* Just connected to WLAN */
+ Serial.println ( "" );
+ Serial.print ( "Connected to " );
+ Serial.println ( ssid );
+ Serial.print ( "IP address: " );
+ Serial.println ( WiFi.localIP() );
+
+ // Setup MDNS responder
+ if (!MDNS.begin(myHostname)) {
+ Serial.println("Error setting up MDNS responder!");
+ } else {
+ Serial.println("mDNS responder started");
+ // Add service to MDNS-SD
+ MDNS.addService("http", "tcp", 80);
+ }
+ } else if (s == WL_NO_SSID_AVAIL) {
+ WiFi.disconnect();
+ }
+ }
+ }
+ // Do work:
+ //DNS
+ dnsServer.processNextRequest();
+ //HTTP
+ server.handleClient();
+}
+
diff --git a/cores/esp32/nefry/inc/DNSServer/examples/CaptivePortalAdvanced/credentials.ino b/cores/esp32/nefry/inc/DNSServer/examples/CaptivePortalAdvanced/credentials.ino
new file mode 100644
index 00000000000..3f9501e7964
--- /dev/null
+++ b/cores/esp32/nefry/inc/DNSServer/examples/CaptivePortalAdvanced/credentials.ino
@@ -0,0 +1,27 @@
+/** Load WLAN credentials from EEPROM */
+void loadCredentials() {
+ EEPROM.begin(512);
+ EEPROM.get(0, ssid);
+ EEPROM.get(0+sizeof(ssid), password);
+ char ok[2+1];
+ EEPROM.get(0+sizeof(ssid)+sizeof(password), ok);
+ EEPROM.end();
+ if (String(ok) != String("OK")) {
+ ssid[0] = 0;
+ password[0] = 0;
+ }
+ Serial.println("Recovered credentials:");
+ Serial.println(ssid);
+ Serial.println(strlen(password)>0?"********":"");
+}
+
+/** Store WLAN credentials to EEPROM */
+void saveCredentials() {
+ EEPROM.begin(512);
+ EEPROM.put(0, ssid);
+ EEPROM.put(0+sizeof(ssid), password);
+ char ok[2+1] = "OK";
+ EEPROM.put(0+sizeof(ssid)+sizeof(password), ok);
+ EEPROM.commit();
+ EEPROM.end();
+}
diff --git a/cores/esp32/nefry/inc/DNSServer/examples/CaptivePortalAdvanced/handleHttp.ino b/cores/esp32/nefry/inc/DNSServer/examples/CaptivePortalAdvanced/handleHttp.ino
new file mode 100644
index 00000000000..50e7823aca8
--- /dev/null
+++ b/cores/esp32/nefry/inc/DNSServer/examples/CaptivePortalAdvanced/handleHttp.ino
@@ -0,0 +1,131 @@
+/** Handle root or redirect to captive portal */
+void handleRoot() {
+ if (captivePortal()) { // If caprive portal redirect instead of displaying the page.
+ return;
+ }
+ server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
+ server.sendHeader("Pragma", "no-cache");
+ server.sendHeader("Expires", "-1");
+ server.setContentLength(CONTENT_LENGTH_UNKNOWN);
+ server.send(200, "text/html", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
+ server.sendContent(
+ ""
+ "HELLO WORLD!!
"
+ );
+ if (server.client().localIP() == apIP) {
+ server.sendContent(String("You are connected through the soft AP: ") + softAP_ssid + "
");
+ } else {
+ server.sendContent(String("You are connected through the wifi network: ") + ssid + "
");
+ }
+ server.sendContent(
+ "You may want to config the wifi connection.
"
+ ""
+ );
+ server.client().stop(); // Stop is needed because we sent no content length
+}
+
+/** Redirect to captive portal if we got a request for another domain. Return true in that case so the page handler do not try to handle the request again. */
+boolean captivePortal() {
+ if (!isIp(server.hostHeader()) && server.hostHeader() != (String(myHostname)+".local")) {
+ Serial.print("Request redirected to captive portal");
+ server.sendHeader("Location", String("http://") + toStringIp(server.client().localIP()), true);
+ server.send ( 302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
+ server.client().stop(); // Stop is needed because we sent no content length
+ return true;
+ }
+ return false;
+}
+
+/** Wifi config page handler */
+void handleWifi() {
+ server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
+ server.sendHeader("Pragma", "no-cache");
+ server.sendHeader("Expires", "-1");
+ server.setContentLength(CONTENT_LENGTH_UNKNOWN);
+ server.send(200, "text/html", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
+ server.sendContent(
+ ""
+ "Wifi config
"
+ );
+ if (server.client().localIP() == apIP) {
+ server.sendContent(String("You are connected through the soft AP: ") + softAP_ssid + "
");
+ } else {
+ server.sendContent(String("You are connected through the wifi network: ") + ssid + "
");
+ }
+ server.sendContent(
+ "\r\n
"
+ "SoftAP config |
"
+ );
+ server.sendContent(String() + "SSID " + String(softAP_ssid) + " |
");
+ server.sendContent(String() + "IP " + toStringIp(WiFi.softAPIP()) + " |
");
+ server.sendContent(
+ "
"
+ "\r\n
"
+ "WLAN config |
"
+ );
+ server.sendContent(String() + "SSID " + String(ssid) + " |
");
+ server.sendContent(String() + "IP " + toStringIp(WiFi.localIP()) + " |
");
+ server.sendContent(
+ "
"
+ "\r\n
"
+ "WLAN list (refresh if any missing) |
"
+ );
+ Serial.println("scan start");
+ int n = WiFi.scanNetworks();
+ Serial.println("scan done");
+ if (n > 0) {
+ for (int i = 0; i < n; i++) {
+ server.sendContent(String() + "\r\nSSID " + WiFi.SSID(i) + String((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":" *") + " (" + WiFi.RSSI(i) + ") |
");
+ }
+ } else {
+ server.sendContent(String() + "No WLAN found |
");
+ }
+ server.sendContent(
+ "
"
+ "\r\n
"
+ "You may want to return to the home page.
"
+ ""
+ );
+ server.client().stop(); // Stop is needed because we sent no content length
+}
+
+/** Handle the WLAN save form and redirect to WLAN config page again */
+void handleWifiSave() {
+ Serial.println("wifi save");
+ server.arg("n").toCharArray(ssid, sizeof(ssid) - 1);
+ server.arg("p").toCharArray(password, sizeof(password) - 1);
+ server.sendHeader("Location", "wifi", true);
+ server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
+ server.sendHeader("Pragma", "no-cache");
+ server.sendHeader("Expires", "-1");
+ server.send ( 302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
+ server.client().stop(); // Stop is needed because we sent no content length
+ saveCredentials();
+ connect = strlen(ssid) > 0; // Request WLAN connect with new credentials if there is a SSID
+}
+
+void handleNotFound() {
+ if (captivePortal()) { // If caprive portal redirect instead of displaying the error page.
+ return;
+ }
+ String message = "File Not Found\n\n";
+ message += "URI: ";
+ message += server.uri();
+ message += "\nMethod: ";
+ message += ( server.method() == HTTP_GET ) ? "GET" : "POST";
+ message += "\nArguments: ";
+ message += server.args();
+ message += "\n";
+
+ for ( uint8_t i = 0; i < server.args(); i++ ) {
+ message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n";
+ }
+ server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
+ server.sendHeader("Pragma", "no-cache");
+ server.sendHeader("Expires", "-1");
+ server.send ( 404, "text/plain", message );
+}
+
diff --git a/cores/esp32/nefry/inc/DNSServer/examples/CaptivePortalAdvanced/tools.ino b/cores/esp32/nefry/inc/DNSServer/examples/CaptivePortalAdvanced/tools.ino
new file mode 100644
index 00000000000..5b6d7893112
--- /dev/null
+++ b/cores/esp32/nefry/inc/DNSServer/examples/CaptivePortalAdvanced/tools.ino
@@ -0,0 +1,21 @@
+/** Is this an IP? */
+boolean isIp(String str) {
+ for (int i = 0; i < str.length(); i++) {
+ int c = str.charAt(i);
+ if (c != '.' && (c < '0' || c > '9')) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/** IP to String? */
+String toStringIp(IPAddress ip) {
+ String res = "";
+ for (int i = 0; i < 3; i++) {
+ res += String((ip >> (8 * i)) & 0xFF) + ".";
+ }
+ res += String(((ip >> 8 * 3)) & 0xFF);
+ return res;
+}
+
diff --git a/cores/esp32/nefry/inc/DNSServer/examples/DNSServer/DNSServer.ino b/cores/esp32/nefry/inc/DNSServer/examples/DNSServer/DNSServer.ino
new file mode 100644
index 00000000000..2916d5ab3ca
--- /dev/null
+++ b/cores/esp32/nefry/inc/DNSServer/examples/DNSServer/DNSServer.ino
@@ -0,0 +1,41 @@
+#include
+#include
+#include
+
+const byte DNS_PORT = 53;
+IPAddress apIP(192, 168, 1, 1);
+DNSServer dnsServer;
+ESP8266WebServer webServer(80);
+
+void setup() {
+ WiFi.mode(WIFI_AP);
+ WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
+ WiFi.softAP("DNSServer example");
+
+ // modify TTL associated with the domain name (in seconds)
+ // default is 60 seconds
+ dnsServer.setTTL(300);
+ // set which return code will be used for all other domains (e.g. sending
+ // ServerFailure instead of NonExistentDomain will reduce number of queries
+ // sent by clients)
+ // default is DNSReplyCode::NonExistentDomain
+ dnsServer.setErrorReplyCode(DNSReplyCode::ServerFailure);
+
+ // start DNS server for a specific domain name
+ dnsServer.start(DNS_PORT, "www.example.com", apIP);
+
+ // simple HTTP server to see that DNS server is working
+ webServer.onNotFound([]() {
+ String message = "Hello World!\n\n";
+ message += "URI: ";
+ message += webServer.uri();
+
+ webServer.send(200, "text/plain", message);
+ });
+ webServer.begin();
+}
+
+void loop() {
+ dnsServer.processNextRequest();
+ webServer.handleClient();
+}
diff --git a/cores/esp32/nefry/inc/DNSServer/library.properties b/cores/esp32/nefry/inc/DNSServer/library.properties
new file mode 100644
index 00000000000..fd257dcca8f
--- /dev/null
+++ b/cores/esp32/nefry/inc/DNSServer/library.properties
@@ -0,0 +1,9 @@
+name=DNSServer
+version=1.1.0
+author=Kristijan Novoselić
+maintainer=Kristijan Novoselić,
+sentence=A simple DNS server for ESP8266.
+paragraph=This library implements a simple DNS server.
+category=Communication
+url=
+architectures=esp32
diff --git a/cores/esp32/nefry/inc/DNSServer/src/DNSServer.cpp b/cores/esp32/nefry/inc/DNSServer/src/DNSServer.cpp
new file mode 100644
index 00000000000..67ee475b37d
--- /dev/null
+++ b/cores/esp32/nefry/inc/DNSServer/src/DNSServer.cpp
@@ -0,0 +1,172 @@
+#include "DNSServer.h"
+#include
+#include
+
+//#define DEBUG
+//#define DEBUG_OUTPUT Serial
+DNSServer::DNSServer()
+{
+ _ttl = htonl(60);
+ _errorReplyCode = DNSReplyCode::NonExistentDomain;
+}
+
+bool DNSServer::start(const uint16_t &port, const String &domainName,
+ const IPAddress &resolvedIP)
+{
+ _port = port;
+ _buffer = NULL;
+ _domainName = domainName;
+ _resolvedIP[0] = resolvedIP[0];
+ _resolvedIP[1] = resolvedIP[1];
+ _resolvedIP[2] = resolvedIP[2];
+ _resolvedIP[3] = resolvedIP[3];
+ downcaseAndRemoveWwwPrefix(_domainName);
+ return _udp.begin(_port) == 1;
+}
+
+void DNSServer::setErrorReplyCode(const DNSReplyCode &replyCode)
+{
+ _errorReplyCode = replyCode;
+}
+
+void DNSServer::setTTL(const uint32_t &ttl)
+{
+ _ttl = htonl(ttl);
+}
+
+void DNSServer::stop()
+{
+ _udp.stop();
+ free(_buffer);
+ _buffer = NULL;
+}
+
+void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
+{
+ domainName.toLowerCase();
+ domainName.replace("www.", "");
+}
+
+void DNSServer::processNextRequest()
+{
+ _currentPacketSize = _udp.parsePacket();
+ if (_currentPacketSize)
+ {
+ if (_buffer != NULL) free(_buffer);
+ _buffer = (unsigned char*)malloc(_currentPacketSize * sizeof(char));
+ if (_buffer == NULL) return;
+ _udp.read(_buffer, _currentPacketSize);
+ _dnsHeader = (DNSHeader*) _buffer;
+
+ if (_dnsHeader->QR == DNS_QR_QUERY &&
+ _dnsHeader->OPCode == DNS_OPCODE_QUERY &&
+ requestIncludesOnlyOneQuestion() &&
+ (_domainName == "*" || getDomainNameWithoutWwwPrefix() == _domainName)
+ )
+ {
+ replyWithIP();
+ }
+ else if (_dnsHeader->QR == DNS_QR_QUERY)
+ {
+ replyWithCustomCode();
+ }
+
+ free(_buffer);
+ _buffer = NULL;
+ }
+}
+
+bool DNSServer::requestIncludesOnlyOneQuestion()
+{
+ return ntohs(_dnsHeader->QDCount) == 1 &&
+ _dnsHeader->ANCount == 0 &&
+ _dnsHeader->NSCount == 0 &&
+ _dnsHeader->ARCount == 0;
+}
+
+String DNSServer::getDomainNameWithoutWwwPrefix()
+{
+ String parsedDomainName = "";
+ if (_buffer == NULL) return parsedDomainName;
+ unsigned char *start = _buffer + 12;
+ if (*start == 0)
+ {
+ return parsedDomainName;
+ }
+ int pos = 0;
+ while(true)
+ {
+ unsigned char labelLength = *(start + pos);
+ for(int i = 0; i < labelLength; i++)
+ {
+ pos++;
+ parsedDomainName += (char)*(start + pos);
+ }
+ pos++;
+ if (*(start + pos) == 0)
+ {
+ downcaseAndRemoveWwwPrefix(parsedDomainName);
+ return parsedDomainName;
+ }
+ else
+ {
+ parsedDomainName += ".";
+ }
+ }
+}
+
+void DNSServer::replyWithIP()
+{
+ if (_buffer == NULL) return;
+ _dnsHeader->QR = DNS_QR_RESPONSE;
+ _dnsHeader->ANCount = _dnsHeader->QDCount;
+ _dnsHeader->QDCount = _dnsHeader->QDCount;
+ //_dnsHeader->RA = 1;
+
+ _udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
+ _udp.write(_buffer, _currentPacketSize);
+
+ _udp.write((uint8_t)192); // answer name is a pointer
+ _udp.write((uint8_t)12); // pointer to offset at 0x00c
+
+ _udp.write((uint8_t)0); // 0x0001 answer is type A query (host address)
+ _udp.write((uint8_t)1);
+
+ _udp.write((uint8_t)0); //0x0001 answer is class IN (internet address)
+ _udp.write((uint8_t)1);
+
+ _udp.write((unsigned char*)&_ttl, 4);
+
+ // Length of RData is 4 bytes (because, in this case, RData is IPv4)
+ _udp.write((uint8_t)0);
+ _udp.write((uint8_t)4);
+ _udp.write(_resolvedIP, sizeof(_resolvedIP));
+ _udp.endPacket();
+
+
+
+ #ifdef DEBUG
+ DEBUG_OUTPUT.print("DNS responds: ");
+ DEBUG_OUTPUT.print(_resolvedIP[0]);
+ DEBUG_OUTPUT.print(".");
+ DEBUG_OUTPUT.print(_resolvedIP[1]);
+ DEBUG_OUTPUT.print(".");
+ DEBUG_OUTPUT.print(_resolvedIP[2]);
+ DEBUG_OUTPUT.print(".");
+ DEBUG_OUTPUT.print(_resolvedIP[3]);
+ DEBUG_OUTPUT.print(" for ");
+ DEBUG_OUTPUT.println(getDomainNameWithoutWwwPrefix());
+ #endif
+}
+
+void DNSServer::replyWithCustomCode()
+{
+ if (_buffer == NULL) return;
+ _dnsHeader->QR = DNS_QR_RESPONSE;
+ _dnsHeader->RCode = (unsigned char)_errorReplyCode;
+ _dnsHeader->QDCount = 0;
+
+ _udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
+ _udp.write(_buffer, sizeof(DNSHeader));
+ _udp.endPacket();
+}
diff --git a/cores/esp32/nefry/inc/DNSServer/src/DNSServer.h b/cores/esp32/nefry/inc/DNSServer/src/DNSServer.h
new file mode 100644
index 00000000000..359e8b148b3
--- /dev/null
+++ b/cores/esp32/nefry/inc/DNSServer/src/DNSServer.h
@@ -0,0 +1,71 @@
+#ifndef DNSServer_h
+#define DNSServer_h
+#include "../../WiFi/src/WiFiUdp.h"
+
+#define DNS_QR_QUERY 0
+#define DNS_QR_RESPONSE 1
+#define DNS_OPCODE_QUERY 0
+
+enum class DNSReplyCode
+{
+ NoError = 0,
+ FormError = 1,
+ ServerFailure = 2,
+ NonExistentDomain = 3,
+ NotImplemented = 4,
+ Refused = 5,
+ YXDomain = 6,
+ YXRRSet = 7,
+ NXRRSet = 8
+};
+
+struct DNSHeader
+{
+ uint16_t ID; // identification number
+ unsigned char RD : 1; // recursion desired
+ unsigned char TC : 1; // truncated message
+ unsigned char AA : 1; // authoritive answer
+ unsigned char OPCode : 4; // message_type
+ unsigned char QR : 1; // query/response flag
+ unsigned char RCode : 4; // response code
+ unsigned char Z : 3; // its z! reserved
+ unsigned char RA : 1; // recursion available
+ uint16_t QDCount; // number of question entries
+ uint16_t ANCount; // number of answer entries
+ uint16_t NSCount; // number of authority entries
+ uint16_t ARCount; // number of resource entries
+};
+
+class DNSServer
+{
+ public:
+ DNSServer();
+ void processNextRequest();
+ void setErrorReplyCode(const DNSReplyCode &replyCode);
+ void setTTL(const uint32_t &ttl);
+
+ // Returns true if successful, false if there are no sockets available
+ bool start(const uint16_t &port,
+ const String &domainName,
+ const IPAddress &resolvedIP);
+ // stops the DNS server
+ void stop();
+
+ private:
+ WiFiUDP _udp;
+ uint16_t _port;
+ String _domainName;
+ unsigned char _resolvedIP[4];
+ int _currentPacketSize;
+ unsigned char* _buffer;
+ DNSHeader* _dnsHeader;
+ uint32_t _ttl;
+ DNSReplyCode _errorReplyCode;
+
+ void downcaseAndRemoveWwwPrefix(String &domainName);
+ String getDomainNameWithoutWwwPrefix();
+ bool requestIncludesOnlyOneQuestion();
+ void replyWithIP();
+ void replyWithCustomCode();
+};
+#endif
\ No newline at end of file
diff --git a/cores/esp32/nefry/inc/ESP32WebServer/keywords.txt b/cores/esp32/nefry/inc/ESP32WebServer/keywords.txt
new file mode 100644
index 00000000000..22e3d74e426
--- /dev/null
+++ b/cores/esp32/nefry/inc/ESP32WebServer/keywords.txt
@@ -0,0 +1,36 @@
+#######################################
+# Syntax Coloring Map For Ultrasound
+#######################################
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+ESP8266WebServer KEYWORD1
+HTTPMethod KEYWORD1
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+
+begin KEYWORD2
+handleClient KEYWORD2
+on KEYWORD2
+addHandler KEYWORD2
+uri KEYWORD2
+method KEYWORD2
+client KEYWORD2
+send KEYWORD2
+arg KEYWORD2
+argName KEYWORD2
+args KEYWORD2
+hasArg KEYWORD2
+onNotFound KEYWORD2
+
+#######################################
+# Constants (LITERAL1)
+#######################################
+
+HTTP_GET LITERAL1
+HTTP_POST LITERAL1
+HTTP_ANY LITERAL1
diff --git a/cores/esp32/nefry/inc/ESP32WebServer/library.properties b/cores/esp32/nefry/inc/ESP32WebServer/library.properties
new file mode 100644
index 00000000000..2771a2bdb34
--- /dev/null
+++ b/cores/esp32/nefry/inc/ESP32WebServer/library.properties
@@ -0,0 +1,9 @@
+name=ESP32WebServer
+version=1.0
+author=Ivan Grokhotkov
+maintainer=Ivan Grokhtkov
+sentence=Simple web server library
+paragraph=The library supports HTTP GET and POST requests, provides argument parsing, handles one client at a time.
+category=Communication
+url=
+architectures=esp32
diff --git a/cores/esp32/nefry/inc/ESP32WebServer/src/ESP32WebServer.cpp b/cores/esp32/nefry/inc/ESP32WebServer/src/ESP32WebServer.cpp
new file mode 100644
index 00000000000..d7dbe773a2f
--- /dev/null
+++ b/cores/esp32/nefry/inc/ESP32WebServer/src/ESP32WebServer.cpp
@@ -0,0 +1,497 @@
+/*
+ ESP32WebServer.cpp - Dead simple web-server.
+ Supports only one simultaneous client, knows how to handle GET and POST.
+
+ Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling)
+*/
+
+
+#include
+#include
+#include "../../WiFi/src/WiFiServer.h"
+#include "../../WiFi/src/WiFiClient.h"
+#include "./ESP32WebServer.h"
+//#include "FS.h"
+#include "detail/RequestHandlersImpl.h"
+
+//#define DEBUG_ESP_HTTP_SERVER
+#ifdef DEBUG_ESP_PORT
+#define DEBUG_OUTPUT DEBUG_ESP_PORT
+#else
+#define DEBUG_OUTPUT Serial
+#endif
+
+const char * AUTHORIZATION_HEADER = "Authorization";
+
+ESP32WebServer::ESP32WebServer(IPAddress addr, int port)
+ : _server(addr, port)
+ , _currentMethod(HTTP_ANY)
+ , _currentHandler(0)
+ , _firstHandler(0)
+ , _lastHandler(0)
+ , _currentArgCount(0)
+ , _currentArgs(0)
+ , _headerKeysCount(0)
+ , _currentHeaders(0)
+ , _contentLength(0)
+{
+}
+
+ESP32WebServer::ESP32WebServer(int port)
+ : _server(port)
+ , _currentMethod(HTTP_ANY)
+ , _currentHandler(0)
+ , _firstHandler(0)
+ , _lastHandler(0)
+ , _currentArgCount(0)
+ , _currentArgs(0)
+ , _headerKeysCount(0)
+ , _currentHeaders(0)
+ , _contentLength(0)
+{
+}
+
+ESP32WebServer::~ESP32WebServer() {
+ if (_currentHeaders)
+ delete[]_currentHeaders;
+ _headerKeysCount = 0;
+ RequestHandler* handler = _firstHandler;
+ while (handler) {
+ RequestHandler* next = handler->next();
+ delete handler;
+ handler = next;
+ }
+ close();
+}
+
+void ESP32WebServer::begin() {
+ _server.begin();
+ if (!_headerKeysCount)
+ collectHeaders(0, 0);
+}
+
+bool ESP32WebServer::authenticate(const char * username, const char * password) {
+ if (hasHeader(AUTHORIZATION_HEADER)) {
+ String authReq = header(AUTHORIZATION_HEADER);
+ if (authReq.startsWith("Basic")) {
+ authReq = authReq.substring(6);
+ authReq.trim();
+ char toencodeLen = strlen(username) + strlen(password) + 1;
+ char *toencode = new char[toencodeLen + 1];
+ if (toencode == NULL) {
+ authReq = String();
+ return false;
+ }
+ char *encoded = new char[base64_encode_expected_len(toencodeLen) + 1];
+ if (encoded == NULL) {
+ authReq = String();
+ delete[] toencode;
+ return false;
+ }
+ sprintf(toencode, "%s:%s", username, password);
+ if (base64_encode_chars(toencode, toencodeLen, encoded) > 0 && authReq.equals(encoded)) {
+ authReq = String();
+ delete[] toencode;
+ delete[] encoded;
+ return true;
+ }
+ delete[] toencode;
+ delete[] encoded;
+ }
+ authReq = String();
+ }
+ return false;
+}
+
+void ESP32WebServer::requestAuthentication() {
+ sendHeader("WWW-Authenticate", "Basic realm=\"Login Required\"");
+ send(401);
+}
+
+void ESP32WebServer::on(const char* uri, ESP32WebServer::THandlerFunction handler) {
+ on(uri, HTTP_ANY, handler);
+}
+
+void ESP32WebServer::on(const char* uri, HTTPMethod method, ESP32WebServer::THandlerFunction fn) {
+ on(uri, method, fn, _fileUploadHandler);
+}
+
+void ESP32WebServer::on(const char* uri, HTTPMethod method, ESP32WebServer::THandlerFunction fn, ESP32WebServer::THandlerFunction ufn) {
+ _addRequestHandler(new FunctionRequestHandler(fn, ufn, uri, method));
+}
+
+void ESP32WebServer::addHandler(RequestHandler* handler) {
+ _addRequestHandler(handler);
+}
+
+void ESP32WebServer::_addRequestHandler(RequestHandler* handler) {
+ if (!_lastHandler) {
+ _firstHandler = handler;
+ _lastHandler = handler;
+ }
+ else {
+ _lastHandler->next(handler);
+ _lastHandler = handler;
+ }
+}
+
+void ESP32WebServer::handleClient() {
+ WiFiClient client = _server.available();
+ if (!client) {
+ return;
+ }
+
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.println("New client");
+#endif
+ _currentClient = client;
+ _statusChange = millis();
+
+ if (!_currentClient.connected()) {
+ _currentClient = WiFiClient();
+ return;
+ }
+ if (!_parseRequest(_currentClient)) {
+ _currentClient = WiFiClient();
+ return;
+ }
+ // Wait for data from client to become available
+ _contentLength = CONTENT_LENGTH_NOT_SET;
+ _handleRequest();
+ if (!_currentClient.connected()) {
+ _currentClient = WiFiClient();
+ return;
+ }
+ _currentClient.flush();
+ _currentClient = WiFiClient();
+}
+
+void ESP32WebServer::close() {
+ _server.end();
+}
+
+void ESP32WebServer::stop() {
+ close();
+}
+
+void ESP32WebServer::sendHeader(const String& name, const String& value, bool first) {
+ String headerLine = name;
+ headerLine += ": ";
+ headerLine += value;
+ headerLine += "\r\n";
+
+ if (first) {
+ _responseHeaders = headerLine + _responseHeaders;
+ }
+ else {
+ _responseHeaders += headerLine;
+ }
+}
+
+
+void ESP32WebServer::_prepareHeader(String& response, int code, const char* content_type, size_t contentLength) {
+ response = "HTTP/1.1 ";
+ response += String(code);
+ response += " ";
+ response += _responseCodeToString(code);
+ response += "\r\n";
+
+ if (!content_type)
+ content_type = "text/html";
+
+ sendHeader("Content-Type", content_type, true);
+ if (_contentLength == CONTENT_LENGTH_NOT_SET) {
+ sendHeader("Content-Length", String(contentLength));
+ }
+ else if (_contentLength != CONTENT_LENGTH_UNKNOWN) {
+ sendHeader("Content-Length", String(_contentLength));
+ }
+ sendHeader("Connection", "close");
+ sendHeader("Access-Control-Allow-Origin", "*");
+
+ response += _responseHeaders;
+ response += "\r\n";
+ _responseHeaders = String();
+}
+
+void ESP32WebServer::send(int code, const char* content_type, const String& content) {
+ String header;
+ _prepareHeader(header, code, content_type, content.length());
+ sendContent(header);
+
+ sendContent(content);
+}
+
+void ESP32WebServer::send_P(int code, PGM_P content_type, PGM_P content) {
+ size_t contentLength = 0;
+
+ if (content != NULL) {
+ contentLength = strlen_P(content);
+ }
+
+ String header;
+ char type[64];
+ memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type));
+ _prepareHeader(header, code, (const char*)type, contentLength);
+ sendContent(header);
+ sendContent_P(content);
+}
+
+void ESP32WebServer::send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength) {
+ String header;
+ char type[64];
+ memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type));
+ _prepareHeader(header, code, (const char*)type, contentLength);
+ sendContent(header);
+ sendContent_P(content, contentLength);
+}
+
+void ESP32WebServer::send(int code, char* content_type, const String& content) {
+ send(code, (const char*)content_type, content);
+}
+
+void ESP32WebServer::send(int code, const String& content_type, const String& content) {
+ send(code, (const char*)content_type.c_str(), content);
+}
+
+void ESP32WebServer::sendContent(const String& content) {
+ const size_t unit_size = HTTP_DOWNLOAD_UNIT_SIZE;
+ size_t size_to_send = content.length();
+ const char* send_start = content.c_str();
+
+ while (size_to_send) {
+ size_t will_send = (size_to_send < unit_size) ? size_to_send : unit_size;
+ size_t sent = _currentClient.write(send_start, will_send);
+ if (sent == 0) {
+ break;
+ }
+ size_to_send -= sent;
+ send_start += sent;
+ }
+}
+
+void ESP32WebServer::sendContent_P(PGM_P content) {
+ char contentUnit[HTTP_DOWNLOAD_UNIT_SIZE + 1];
+
+ contentUnit[HTTP_DOWNLOAD_UNIT_SIZE] = '\0';
+
+ while (content != NULL) {
+ size_t contentUnitLen;
+ PGM_P contentNext;
+
+ // due to the memccpy signature, lots of casts are needed
+ contentNext = (PGM_P)memccpy_P((void*)contentUnit, (PGM_VOID_P)content, 0, HTTP_DOWNLOAD_UNIT_SIZE);
+
+ if (contentNext == NULL) {
+ // no terminator, more data available
+ content += HTTP_DOWNLOAD_UNIT_SIZE;
+ contentUnitLen = HTTP_DOWNLOAD_UNIT_SIZE;
+ }
+ else {
+ // reached terminator. Do not send the terminator
+ contentUnitLen = contentNext - contentUnit - 1;
+ content = NULL;
+ }
+
+ // write is so overloaded, had to use the cast to get it pick the right one
+ _currentClient.write((const char*)contentUnit, contentUnitLen);
+ }
+}
+
+void ESP32WebServer::sendContent_P(PGM_P content, size_t size) {
+ char contentUnit[HTTP_DOWNLOAD_UNIT_SIZE + 1];
+ contentUnit[HTTP_DOWNLOAD_UNIT_SIZE] = '\0';
+ size_t remaining_size = size;
+
+ while (content != NULL && remaining_size > 0) {
+ size_t contentUnitLen = HTTP_DOWNLOAD_UNIT_SIZE;
+
+ if (remaining_size < HTTP_DOWNLOAD_UNIT_SIZE) contentUnitLen = remaining_size;
+ // due to the memcpy signature, lots of casts are needed
+ memcpy_P((void*)contentUnit, (PGM_VOID_P)content, contentUnitLen);
+
+ content += contentUnitLen;
+ remaining_size -= contentUnitLen;
+
+ // write is so overloaded, had to use the cast to get it pick the right one
+ _currentClient.write((const char*)contentUnit, contentUnitLen);
+ }
+}
+
+
+String ESP32WebServer::arg(String name) {
+ for (int i = 0; i < _currentArgCount; ++i) {
+ if (_currentArgs[i].key == name)
+ return _currentArgs[i].value;
+ }
+ return String();
+}
+
+String ESP32WebServer::arg(int i) {
+ if (i < _currentArgCount)
+ return _currentArgs[i].value;
+ return String();
+}
+
+String ESP32WebServer::argName(int i) {
+ if (i < _currentArgCount)
+ return _currentArgs[i].key;
+ return String();
+}
+
+int ESP32WebServer::args() {
+ return _currentArgCount;
+}
+
+bool ESP32WebServer::hasArg(String name) {
+ for (int i = 0; i < _currentArgCount; ++i) {
+ if (_currentArgs[i].key == name)
+ return true;
+ }
+ return false;
+}
+
+
+String ESP32WebServer::header(String name) {
+ for (int i = 0; i < _headerKeysCount; ++i) {
+ if (_currentHeaders[i].key == name)
+ return _currentHeaders[i].value;
+ }
+ return String();
+}
+
+void ESP32WebServer::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) {
+ _headerKeysCount = headerKeysCount + 1;
+ if (_currentHeaders)
+ delete[]_currentHeaders;
+ _currentHeaders = new RequestArgument[_headerKeysCount];
+ _currentHeaders[0].key = AUTHORIZATION_HEADER;
+ for (int i = 1; i < _headerKeysCount; i++) {
+ _currentHeaders[i].key = headerKeys[i - 1];
+ }
+}
+
+String ESP32WebServer::header(int i) {
+ if (i < _headerKeysCount)
+ return _currentHeaders[i].value;
+ return String();
+}
+
+String ESP32WebServer::headerName(int i) {
+ if (i < _headerKeysCount)
+ return _currentHeaders[i].key;
+ return String();
+}
+
+int ESP32WebServer::headers() {
+ return _headerKeysCount;
+}
+
+bool ESP32WebServer::hasHeader(String name) {
+ for (int i = 0; i < _headerKeysCount; ++i) {
+ if ((_currentHeaders[i].key == name) && (_currentHeaders[i].value.length() > 0))
+ return true;
+ }
+ return false;
+}
+
+String ESP32WebServer::hostHeader() {
+ return _hostHeader;
+}
+
+void ESP32WebServer::onFileUpload(THandlerFunction fn) {
+ _fileUploadHandler = fn;
+}
+
+void ESP32WebServer::onNotFound(THandlerFunction fn) {
+ _notFoundHandler = fn;
+}
+
+void ESP32WebServer::_handleRequest() {
+ bool handled = false;
+ if (!_currentHandler) {
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.println("request handler not found");
+#endif
+ }
+ else {
+ handled = _currentHandler->handle(*this, _currentMethod, _currentUri);
+#ifdef DEBUG_ESP_HTTP_SERVER
+ if (!handled) {
+ DEBUG_OUTPUT.println("request handler failed to handle request");
+ }
+#endif
+ }
+
+ if (!handled) {
+ if (_notFoundHandler) {
+ _notFoundHandler();
+ }
+ else {
+ send(404, "text/plain", String("Not found: ") + _currentUri);
+ }
+ }
+
+ _currentUri = String();
+}
+
+String ESP32WebServer::_responseCodeToString(int code) {
+ switch (code) {
+ case 100: return F("Continue");
+ case 101: return F("Switching Protocols");
+ case 200: return F("OK");
+ case 201: return F("Created");
+ case 202: return F("Accepted");
+ case 203: return F("Non-Authoritative Information");
+ case 204: return F("No Content");
+ case 205: return F("Reset Content");
+ case 206: return F("Partial Content");
+ case 300: return F("Multiple Choices");
+ case 301: return F("Moved Permanently");
+ case 302: return F("Found");
+ case 303: return F("See Other");
+ case 304: return F("Not Modified");
+ case 305: return F("Use Proxy");
+ case 307: return F("Temporary Redirect");
+ case 400: return F("Bad Request");
+ case 401: return F("Unauthorized");
+ case 402: return F("Payment Required");
+ case 403: return F("Forbidden");
+ case 404: return F("Not Found");
+ case 405: return F("Method Not Allowed");
+ case 406: return F("Not Acceptable");
+ case 407: return F("Proxy Authentication Required");
+ case 408: return F("Request Time-out");
+ case 409: return F("Conflict");
+ case 410: return F("Gone");
+ case 411: return F("Length Required");
+ case 412: return F("Precondition Failed");
+ case 413: return F("Request Entity Too Large");
+ case 414: return F("Request-URI Too Large");
+ case 415: return F("Unsupported Media Type");
+ case 416: return F("Requested range not satisfiable");
+ case 417: return F("Expectation Failed");
+ case 500: return F("Internal Server Error");
+ case 501: return F("Not Implemented");
+ case 502: return F("Bad Gateway");
+ case 503: return F("Service Unavailable");
+ case 504: return F("Gateway Time-out");
+ case 505: return F("HTTP Version not supported");
+ default: return "";
+ }
+}
diff --git a/cores/esp32/nefry/inc/ESP32WebServer/src/ESP32WebServer.h b/cores/esp32/nefry/inc/ESP32WebServer/src/ESP32WebServer.h
new file mode 100644
index 00000000000..c51f5b84d10
--- /dev/null
+++ b/cores/esp32/nefry/inc/ESP32WebServer/src/ESP32WebServer.h
@@ -0,0 +1,175 @@
+/*
+ ESP32WebServer.h - Dead simple web-server.
+ Supports only one simultaneous client, knows how to handle GET and POST.
+
+ Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling)
+*/
+
+
+#ifndef ESP32WebServer_H
+#define ESP32WebServer_H
+
+#include
+#include "../../WiFi/src/WiFi.h"
+
+enum HTTPMethod { HTTP_ANY, HTTP_GET, HTTP_POST, HTTP_PUT, HTTP_PATCH, HTTP_DELETE, HTTP_OPTIONS };
+enum HTTPUploadStatus { UPLOAD_FILE_START, UPLOAD_FILE_WRITE, UPLOAD_FILE_END,
+ UPLOAD_FILE_ABORTED };
+
+#define HTTP_DOWNLOAD_UNIT_SIZE 1460
+#define HTTP_UPLOAD_BUFLEN 2048
+#define HTTP_MAX_DATA_WAIT 1000 //ms to wait for the client to send the request
+#define HTTP_MAX_POST_WAIT 1000 //ms to wait for POST data to arrive
+#define HTTP_MAX_CLOSE_WAIT 2000 //ms to wait for the client to close the connection
+
+#define CONTENT_LENGTH_UNKNOWN ((size_t) -1)
+#define CONTENT_LENGTH_NOT_SET ((size_t) -2)
+
+class ESP32WebServer;
+
+typedef struct {
+ HTTPUploadStatus status;
+ String filename;
+ String name;
+ String type;
+ size_t totalSize; // file size
+ size_t currentSize; // size of data currently in buf
+ uint8_t buf[HTTP_UPLOAD_BUFLEN];
+} HTTPUpload;
+
+#include "detail/RequestHandler.h"
+
+
+class ESP32WebServer
+{
+public:
+ ESP32WebServer(IPAddress addr, int port = 80);
+ ESP32WebServer(int port = 80);
+ ~ESP32WebServer();
+
+ void begin();
+ void handleClient();
+
+ void close();
+ void stop();
+
+ bool authenticate(const char * username, const char * password);
+ void requestAuthentication();
+
+ typedef std::function THandlerFunction;
+ void on(const char* uri, THandlerFunction handler);
+ void on(const char* uri, HTTPMethod method, THandlerFunction fn);
+ void on(const char* uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn);
+ void addHandler(RequestHandler* handler);
+ void onNotFound(THandlerFunction fn); //called when handler is not assigned
+ void onFileUpload(THandlerFunction fn); //handle file uploads
+
+ String uri() { return _currentUri; }
+ HTTPMethod method() { return _currentMethod; }
+ WiFiClient client() { return _currentClient; }
+ HTTPUpload& upload() { return _currentUpload; }
+
+ String arg(String name); // get request argument value by name
+ String arg(int i); // get request argument value by number
+ String argName(int i); // get request argument name by number
+ int args(); // get arguments count
+ bool hasArg(String name); // check if argument exists
+ void collectHeaders(const char* headerKeys[], const size_t headerKeysCount); // set the request headers to collect
+ String header(String name); // get request header value by name
+ String header(int i); // get request header value by number
+ String headerName(int i); // get request header name by number
+ int headers(); // get header count
+ bool hasHeader(String name); // check if header exists
+
+ String hostHeader(); // get request host header if available or empty String if not
+
+ // send response to the client
+ // code - HTTP response code, can be 200 or 404
+ // content_type - HTTP content type, like "text/plain" or "image/png"
+ // content - actual content body
+ void send(int code, const char* content_type = NULL, const String& content = String(""));
+ void send(int code, char* content_type, const String& content);
+ void send(int code, const String& content_type, const String& content);
+ void send_P(int code, PGM_P content_type, PGM_P content);
+ void send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength);
+
+ void setContentLength(size_t contentLength) { _contentLength = contentLength; }
+ void sendHeader(const String& name, const String& value, bool first = false);
+ void sendContent(const String& content);
+ void sendContent_P(PGM_P content);
+ void sendContent_P(PGM_P content, size_t size);
+
+ static String urlDecode(const String& text);
+
+template size_t streamFile(T &file, const String& contentType){
+ setContentLength(file.size());
+ if (String(file.name()).endsWith(".gz") &&
+ contentType != "application/x-gzip" &&
+ contentType != "application/octet-stream"){
+ sendHeader("Content-Encoding", "gzip");
+ }
+ send(200, contentType, "");
+ return _currentClient.write(file, HTTP_DOWNLOAD_UNIT_SIZE);
+}
+
+protected:
+ void _addRequestHandler(RequestHandler* handler);
+ void _handleRequest();
+ bool _parseRequest(WiFiClient& client);
+ void _parseArguments(String data);
+ static String _responseCodeToString(int code);
+ bool _parseForm(WiFiClient& client, String boundary, uint32_t len);
+ bool _parseFormUploadAborted();
+ void _uploadWriteByte(uint8_t b);
+ uint8_t _uploadReadByte(WiFiClient& client);
+ void _prepareHeader(String& response, int code, const char* content_type, size_t contentLength);
+ bool _collectHeader(const char* headerName, const char* headerValue);
+
+ struct RequestArgument {
+ String key;
+ String value;
+ };
+
+ WiFiServer _server;
+
+ WiFiClient _currentClient;
+ HTTPMethod _currentMethod;
+ String _currentUri;
+ unsigned long _statusChange;
+
+ RequestHandler* _currentHandler;
+ RequestHandler* _firstHandler;
+ RequestHandler* _lastHandler;
+ THandlerFunction _notFoundHandler;
+ THandlerFunction _fileUploadHandler;
+
+ int _currentArgCount;
+ RequestArgument* _currentArgs;
+ HTTPUpload _currentUpload;
+
+ int _headerKeysCount;
+ RequestArgument* _currentHeaders;
+ size_t _contentLength;
+ String _responseHeaders;
+
+ String _hostHeader;
+
+};
+
+
+#endif //ESP32WebServer_H
diff --git a/cores/esp32/nefry/inc/ESP32WebServer/src/Parsing.cpp b/cores/esp32/nefry/inc/ESP32WebServer/src/Parsing.cpp
new file mode 100644
index 00000000000..ed5edcc947e
--- /dev/null
+++ b/cores/esp32/nefry/inc/ESP32WebServer/src/Parsing.cpp
@@ -0,0 +1,589 @@
+/*
+ Parsing.cpp - HTTP request parsing.
+
+ Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling)
+*/
+
+#include
+#include "../../WiFi/src/WiFiServer.h"
+#include "../../WiFi/src/WiFiClient.h"
+#include "ESP32WebServer.h"
+
+//#define DEBUG_ESP_HTTP_SERVER
+#ifdef DEBUG_ESP_PORT
+#define DEBUG_OUTPUT DEBUG_ESP_PORT
+#else
+#define DEBUG_OUTPUT Serial
+#endif
+
+static char* readBytesWithTimeout(WiFiClient& client, size_t maxLength, size_t& dataLength, int timeout_ms)
+{
+ char *buf = nullptr;
+ dataLength = 0;
+ while (dataLength < maxLength) {
+ int tries = timeout_ms;
+ size_t newLength;
+ while (!(newLength = client.available()) && tries--) delay(1);
+ if (!newLength) {
+ break;
+ }
+ if (!buf) {
+ buf = (char *) malloc(newLength + 1);
+ if (!buf) {
+ return nullptr;
+ }
+ }
+ else {
+ char* newBuf = (char *) realloc(buf, dataLength + newLength + 1);
+ if (!newBuf) {
+ free(buf);
+ return nullptr;
+ }
+ buf = newBuf;
+ }
+ client.readBytes(buf + dataLength, newLength);
+ dataLength += newLength;
+ buf[dataLength] = '\0';
+ }
+ return buf;
+}
+
+bool ESP32WebServer::_parseRequest(WiFiClient& client) {
+ // Read the first line of HTTP request
+ String req = client.readStringUntil('\r');
+ client.readStringUntil('\n');
+ //reset header value
+ for (int i = 0; i < _headerKeysCount; ++i) {
+ _currentHeaders[i].value =String();
+ }
+
+ // First line of HTTP request looks like "GET /path HTTP/1.1"
+ // Retrieve the "/path" part by finding the spaces
+ int addr_start = req.indexOf(' ');
+ int addr_end = req.indexOf(' ', addr_start + 1);
+ if (addr_start == -1 || addr_end == -1) {
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("Invalid request: ");
+ DEBUG_OUTPUT.println(req);
+#endif
+ return false;
+ }
+
+ String methodStr = req.substring(0, addr_start);
+ String url = req.substring(addr_start + 1, addr_end);
+ String searchStr = "";
+ int hasSearch = url.indexOf('?');
+ if (hasSearch != -1){
+ searchStr = url.substring(hasSearch + 1);
+ url = url.substring(0, hasSearch);
+ }
+ _currentUri = url;
+
+ HTTPMethod method = HTTP_GET;
+ if (methodStr == "POST") {
+ method = HTTP_POST;
+ } else if (methodStr == "DELETE") {
+ method = HTTP_DELETE;
+ } else if (methodStr == "OPTIONS") {
+ method = HTTP_OPTIONS;
+ } else if (methodStr == "PUT") {
+ method = HTTP_PUT;
+ } else if (methodStr == "PATCH") {
+ method = HTTP_PATCH;
+ }
+ _currentMethod = method;
+
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("method: ");
+ DEBUG_OUTPUT.print(methodStr);
+ DEBUG_OUTPUT.print(" url: ");
+ DEBUG_OUTPUT.print(url);
+ DEBUG_OUTPUT.print(" search: ");
+ DEBUG_OUTPUT.println(searchStr);
+#endif
+
+ //attach handler
+ RequestHandler* handler;
+ for (handler = _firstHandler; handler; handler = handler->next()) {
+ if (handler->canHandle(_currentMethod, _currentUri))
+ break;
+ }
+ _currentHandler = handler;
+
+ String formData;
+ // below is needed only when POST type request
+ if (method == HTTP_POST || method == HTTP_PUT || method == HTTP_PATCH || method == HTTP_DELETE){
+ String boundaryStr;
+ String headerName;
+ String headerValue;
+ bool isForm = false;
+ uint32_t contentLength = 0;
+ //parse headers
+ while(1){
+ req = client.readStringUntil('\r');
+ client.readStringUntil('\n');
+ if (req == "") break;//no moar headers
+ int headerDiv = req.indexOf(':');
+ if (headerDiv == -1){
+ break;
+ }
+ headerName = req.substring(0, headerDiv);
+ headerValue = req.substring(headerDiv + 1);
+ headerValue.trim();
+ _collectHeader(headerName.c_str(),headerValue.c_str());
+
+ #ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("headerName: ");
+ DEBUG_OUTPUT.println(headerName);
+ DEBUG_OUTPUT.print("headerValue: ");
+ DEBUG_OUTPUT.println(headerValue);
+ #endif
+
+ if (headerName == "Content-Type"){
+ if (headerValue.startsWith("text/plain")){
+ isForm = false;
+ } else if (headerValue.startsWith("multipart/form-data")){
+ boundaryStr = headerValue.substring(headerValue.indexOf('=')+1);
+ isForm = true;
+ }
+ } else if (headerName == "Content-Length"){
+ contentLength = headerValue.toInt();
+ } else if (headerName == "Host"){
+ _hostHeader = headerValue;
+ }
+ }
+
+ if (!isForm){
+ size_t plainLength;
+ char* plainBuf = readBytesWithTimeout(client, contentLength, plainLength, HTTP_MAX_POST_WAIT);
+ if (plainLength < contentLength) {
+ free(plainBuf);
+ return false;
+ }
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("Plain: ");
+ DEBUG_OUTPUT.println(plainBuf);
+#endif
+ if (contentLength > 0) {
+ if (searchStr != "") searchStr += '&';
+ if(plainBuf[0] == '{' || plainBuf[0] == '[' || strstr(plainBuf, "=") == NULL){
+ //plain post json or other data
+ searchStr += "plain=";
+ searchStr += plainBuf;
+ } else {
+ searchStr += plainBuf;
+ }
+ free(plainBuf);
+ }
+ }
+ _parseArguments(searchStr);
+ if (isForm){
+ if (!_parseForm(client, boundaryStr, contentLength)) {
+ return false;
+ }
+ }
+ } else {
+ String headerName;
+ String headerValue;
+ //parse headers
+ while(1){
+ req = client.readStringUntil('\r');
+ client.readStringUntil('\n');
+ if (req == "") break;//no moar headers
+ int headerDiv = req.indexOf(':');
+ if (headerDiv == -1){
+ break;
+ }
+ headerName = req.substring(0, headerDiv);
+ headerValue = req.substring(headerDiv + 2);
+ _collectHeader(headerName.c_str(),headerValue.c_str());
+
+ #ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("headerName: ");
+ DEBUG_OUTPUT.println(headerName);
+ DEBUG_OUTPUT.print("headerValue: ");
+ DEBUG_OUTPUT.println(headerValue);
+ #endif
+
+ if (headerName == "Host"){
+ _hostHeader = headerValue;
+ }
+ }
+ _parseArguments(searchStr);
+ }
+ client.flush();
+
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("Request: ");
+ DEBUG_OUTPUT.println(url);
+ DEBUG_OUTPUT.print(" Arguments: ");
+ DEBUG_OUTPUT.println(searchStr);
+#endif
+
+ return true;
+}
+
+bool ESP32WebServer::_collectHeader(const char* headerName, const char* headerValue) {
+ for (int i = 0; i < _headerKeysCount; i++) {
+ if (_currentHeaders[i].key==headerName) {
+ _currentHeaders[i].value=headerValue;
+ return true;
+ }
+ }
+ return false;
+}
+
+void ESP32WebServer::_parseArguments(String data) {
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("args: ");
+ DEBUG_OUTPUT.println(data);
+#endif
+ if (_currentArgs)
+ delete[] _currentArgs;
+ _currentArgs = 0;
+ if (data.length() == 0) {
+ _currentArgCount = 0;
+ return;
+ }
+ _currentArgCount = 1;
+
+ for (int i = 0; i < (int)data.length(); ) {
+ i = data.indexOf('&', i);
+ if (i == -1)
+ break;
+ ++i;
+ ++_currentArgCount;
+ }
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("args count: ");
+ DEBUG_OUTPUT.println(_currentArgCount);
+#endif
+
+ _currentArgs = new RequestArgument[_currentArgCount];
+ int pos = 0;
+ int iarg;
+ for (iarg = 0; iarg < _currentArgCount;) {
+ int equal_sign_index = data.indexOf('=', pos);
+ int next_arg_index = data.indexOf('&', pos);
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("pos ");
+ DEBUG_OUTPUT.print(pos);
+ DEBUG_OUTPUT.print("=@ ");
+ DEBUG_OUTPUT.print(equal_sign_index);
+ DEBUG_OUTPUT.print(" &@ ");
+ DEBUG_OUTPUT.println(next_arg_index);
+#endif
+ if ((equal_sign_index == -1) || ((equal_sign_index > next_arg_index) && (next_arg_index != -1))) {
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("arg missing value: ");
+ DEBUG_OUTPUT.println(iarg);
+#endif
+ if (next_arg_index == -1)
+ break;
+ pos = next_arg_index + 1;
+ continue;
+ }
+ RequestArgument& arg = _currentArgs[iarg];
+ arg.key = data.substring(pos, equal_sign_index);
+ arg.value = urlDecode(data.substring(equal_sign_index + 1, next_arg_index));
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("arg ");
+ DEBUG_OUTPUT.print(iarg);
+ DEBUG_OUTPUT.print(" key: ");
+ DEBUG_OUTPUT.print(arg.key);
+ DEBUG_OUTPUT.print(" value: ");
+ DEBUG_OUTPUT.println(arg.value);
+#endif
+ ++iarg;
+ if (next_arg_index == -1)
+ break;
+ pos = next_arg_index + 1;
+ }
+ _currentArgCount = iarg;
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("args count: ");
+ DEBUG_OUTPUT.println(_currentArgCount);
+#endif
+
+}
+
+void ESP32WebServer::_uploadWriteByte(uint8_t b){
+ if (_currentUpload.currentSize == HTTP_UPLOAD_BUFLEN){
+ if(_currentHandler && _currentHandler->canUpload(_currentUri))
+ _currentHandler->upload(*this, _currentUri, _currentUpload);
+ _currentUpload.totalSize += _currentUpload.currentSize;
+ _currentUpload.currentSize = 0;
+ }
+ _currentUpload.buf[_currentUpload.currentSize++] = b;
+}
+
+uint8_t ESP32WebServer::_uploadReadByte(WiFiClient& client){
+ int res = client.read();
+ if(res == -1){
+ while(!client.available() && client.connected())
+ yield();
+ res = client.read();
+ }
+ return (uint8_t)res;
+}
+
+bool ESP32WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t len){
+
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("Parse Form: Boundary: ");
+ DEBUG_OUTPUT.print(boundary);
+ DEBUG_OUTPUT.print(" Length: ");
+ DEBUG_OUTPUT.println(len);
+#endif
+ String line;
+ int retry = 0;
+ do {
+ line = client.readStringUntil('\r');
+ ++retry;
+ } while (line.length() == 0 && retry < 3);
+
+ client.readStringUntil('\n');
+ //start reading the form
+ if (line == ("--"+boundary)){
+ RequestArgument* postArgs = new RequestArgument[32];
+ int postArgsLen = 0;
+ while(1){
+ String argName;
+ String argValue;
+ String argType;
+ String argFilename;
+ bool argIsFile = false;
+
+ line = client.readStringUntil('\r');
+ client.readStringUntil('\n');
+ if (line.startsWith("Content-Disposition")){
+ int nameStart = line.indexOf('=');
+ if (nameStart != -1){
+ argName = line.substring(nameStart+2);
+ nameStart = argName.indexOf('=');
+ if (nameStart == -1){
+ argName = argName.substring(0, argName.length() - 1);
+ } else {
+ argFilename = argName.substring(nameStart+2, argName.length() - 1);
+ argName = argName.substring(0, argName.indexOf('"'));
+ argIsFile = true;
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("PostArg FileName: ");
+ DEBUG_OUTPUT.println(argFilename);
+#endif
+ //use GET to set the filename if uploading using blob
+ if (argFilename == "blob" && hasArg("filename")) argFilename = arg("filename");
+ }
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("PostArg Name: ");
+ DEBUG_OUTPUT.println(argName);
+#endif
+ argType = "text/plain";
+ line = client.readStringUntil('\r');
+ client.readStringUntil('\n');
+ if (line.startsWith("Content-Type")){
+ argType = line.substring(line.indexOf(':')+2);
+ //skip next line
+ client.readStringUntil('\r');
+ client.readStringUntil('\n');
+ }
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("PostArg Type: ");
+ DEBUG_OUTPUT.println(argType);
+#endif
+ if (!argIsFile){
+ while(1){
+ line = client.readStringUntil('\r');
+ client.readStringUntil('\n');
+ if (line.startsWith("--"+boundary)) break;
+ if (argValue.length() > 0) argValue += "\n";
+ argValue += line;
+ }
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("PostArg Value: ");
+ DEBUG_OUTPUT.println(argValue);
+ DEBUG_OUTPUT.println();
+#endif
+
+ RequestArgument& arg = postArgs[postArgsLen++];
+ arg.key = argName;
+ arg.value = argValue;
+
+ if (line == ("--"+boundary+"--")){
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.println("Done Parsing POST");
+#endif
+ break;
+ }
+ } else {
+ _currentUpload.status = UPLOAD_FILE_START;
+ _currentUpload.name = argName;
+ _currentUpload.filename = argFilename;
+ _currentUpload.type = argType;
+ _currentUpload.totalSize = 0;
+ _currentUpload.currentSize = 0;
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("Start File: ");
+ DEBUG_OUTPUT.print(_currentUpload.filename);
+ DEBUG_OUTPUT.print(" Type: ");
+ DEBUG_OUTPUT.println(_currentUpload.type);
+#endif
+ if(_currentHandler && _currentHandler->canUpload(_currentUri))
+ _currentHandler->upload(*this, _currentUri, _currentUpload);
+ _currentUpload.status = UPLOAD_FILE_WRITE;
+ uint8_t argByte = _uploadReadByte(client);
+readfile:
+ while(argByte != 0x0D){
+ if (!client.connected()) return _parseFormUploadAborted();
+ _uploadWriteByte(argByte);
+ argByte = _uploadReadByte(client);
+ }
+
+ argByte = _uploadReadByte(client);
+ if (!client.connected()) return _parseFormUploadAborted();
+ if (argByte == 0x0A){
+ argByte = _uploadReadByte(client);
+ if (!client.connected()) return _parseFormUploadAborted();
+ if ((char)argByte != '-'){
+ //continue reading the file
+ _uploadWriteByte(0x0D);
+ _uploadWriteByte(0x0A);
+ goto readfile;
+ } else {
+ argByte = _uploadReadByte(client);
+ if (!client.connected()) return _parseFormUploadAborted();
+ if ((char)argByte != '-'){
+ //continue reading the file
+ _uploadWriteByte(0x0D);
+ _uploadWriteByte(0x0A);
+ _uploadWriteByte((uint8_t)('-'));
+ goto readfile;
+ }
+ }
+
+ uint8_t endBuf[boundary.length()];
+ client.readBytes(endBuf, boundary.length());
+
+ if (strstr((const char*)endBuf, boundary.c_str()) != NULL){
+ if(_currentHandler && _currentHandler->canUpload(_currentUri))
+ _currentHandler->upload(*this, _currentUri, _currentUpload);
+ _currentUpload.totalSize += _currentUpload.currentSize;
+ _currentUpload.status = UPLOAD_FILE_END;
+ if(_currentHandler && _currentHandler->canUpload(_currentUri))
+ _currentHandler->upload(*this, _currentUri, _currentUpload);
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("End File: ");
+ DEBUG_OUTPUT.print(_currentUpload.filename);
+ DEBUG_OUTPUT.print(" Type: ");
+ DEBUG_OUTPUT.print(_currentUpload.type);
+ DEBUG_OUTPUT.print(" Size: ");
+ DEBUG_OUTPUT.println(_currentUpload.totalSize);
+#endif
+ line = client.readStringUntil(0x0D);
+ client.readStringUntil(0x0A);
+ if (line == "--"){
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.println("Done Parsing POST");
+#endif
+ break;
+ }
+ continue;
+ } else {
+ _uploadWriteByte(0x0D);
+ _uploadWriteByte(0x0A);
+ _uploadWriteByte((uint8_t)('-'));
+ _uploadWriteByte((uint8_t)('-'));
+ uint32_t i = 0;
+ while(i < boundary.length()){
+ _uploadWriteByte(endBuf[i++]);
+ }
+ argByte = _uploadReadByte(client);
+ goto readfile;
+ }
+ } else {
+ _uploadWriteByte(0x0D);
+ goto readfile;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ int iarg;
+ int totalArgs = ((32 - postArgsLen) < _currentArgCount)?(32 - postArgsLen):_currentArgCount;
+ for (iarg = 0; iarg < totalArgs; iarg++){
+ RequestArgument& arg = postArgs[postArgsLen++];
+ arg.key = _currentArgs[iarg].key;
+ arg.value = _currentArgs[iarg].value;
+ }
+ if (_currentArgs) delete[] _currentArgs;
+ _currentArgs = new RequestArgument[postArgsLen];
+ for (iarg = 0; iarg < postArgsLen; iarg++){
+ RequestArgument& arg = _currentArgs[iarg];
+ arg.key = postArgs[iarg].key;
+ arg.value = postArgs[iarg].value;
+ }
+ _currentArgCount = iarg;
+ if (postArgs) delete[] postArgs;
+ return true;
+ }
+#ifdef DEBUG_ESP_HTTP_SERVER
+ DEBUG_OUTPUT.print("Error: line: ");
+ DEBUG_OUTPUT.println(line);
+#endif
+ return false;
+}
+
+String ESP32WebServer::urlDecode(const String& text)
+{
+ String decoded = "";
+ char temp[] = "0x00";
+ unsigned int len = text.length();
+ unsigned int i = 0;
+ while (i < len)
+ {
+ char decodedChar;
+ char encodedChar = text.charAt(i++);
+ if ((encodedChar == '%') && (i + 1 < len))
+ {
+ temp[2] = text.charAt(i++);
+ temp[3] = text.charAt(i++);
+
+ decodedChar = strtol(temp, NULL, 16);
+ }
+ else {
+ if (encodedChar == '+')
+ {
+ decodedChar = ' ';
+ }
+ else {
+ decodedChar = encodedChar; // normal ascii char
+ }
+ }
+ decoded += decodedChar;
+ }
+ return decoded;
+}
+
+bool ESP32WebServer::_parseFormUploadAborted(){
+ _currentUpload.status = UPLOAD_FILE_ABORTED;
+ if(_currentHandler && _currentHandler->canUpload(_currentUri))
+ _currentHandler->upload(*this, _currentUri, _currentUpload);
+ return false;
+}
diff --git a/cores/esp32/nefry/inc/ESP32WebServer/src/detail/RequestHandler.h b/cores/esp32/nefry/inc/ESP32WebServer/src/detail/RequestHandler.h
new file mode 100644
index 00000000000..84524877c67
--- /dev/null
+++ b/cores/esp32/nefry/inc/ESP32WebServer/src/detail/RequestHandler.h
@@ -0,0 +1,19 @@
+#ifndef REQUESTHANDLER_H
+#define REQUESTHANDLER_H
+
+class RequestHandler {
+public:
+ virtual ~RequestHandler() { }
+ virtual bool canHandle(HTTPMethod method, String uri) { return false; }
+ virtual bool canUpload(String uri) { return false; }
+ virtual bool handle(ESP32WebServer& server, HTTPMethod requestMethod, String requestUri) { return false; }
+ virtual void upload(ESP32WebServer& server, String requestUri, HTTPUpload& upload) {}
+
+ RequestHandler* next() { return _next; }
+ void next(RequestHandler* r) { _next = r; }
+
+private:
+ RequestHandler* _next = nullptr;
+};
+
+#endif //REQUESTHANDLER_H
diff --git a/cores/esp32/nefry/inc/ESP32WebServer/src/detail/RequestHandlersImpl.h b/cores/esp32/nefry/inc/ESP32WebServer/src/detail/RequestHandlersImpl.h
new file mode 100644
index 00000000000..851dbe95d44
--- /dev/null
+++ b/cores/esp32/nefry/inc/ESP32WebServer/src/detail/RequestHandlersImpl.h
@@ -0,0 +1,55 @@
+#ifndef REQUESTHANDLERSIMPL_H
+#define REQUESTHANDLERSIMPL_H
+
+#include "RequestHandler.h"
+
+class FunctionRequestHandler : public RequestHandler {
+public:
+ FunctionRequestHandler(ESP32WebServer::THandlerFunction fn, ESP32WebServer::THandlerFunction ufn, const char* uri, HTTPMethod method)
+ : _fn(fn)
+ , _ufn(ufn)
+ , _uri(uri)
+ , _method(method)
+ {
+ }
+
+ bool canHandle(HTTPMethod requestMethod, String requestUri) override {
+ if (_method != HTTP_ANY && _method != requestMethod)
+ return false;
+
+ if (requestUri != _uri)
+ return false;
+
+ return true;
+ }
+
+ bool canUpload(String requestUri) override {
+ if (!_ufn || !canHandle(HTTP_POST, requestUri))
+ return false;
+
+ return true;
+ }
+
+ bool handle(ESP32WebServer& server, HTTPMethod requestMethod, String requestUri) override {
+ if (!canHandle(requestMethod, requestUri))
+ return false;
+
+ _fn();
+ return true;
+ }
+
+ void upload(ESP32WebServer& server, String requestUri, HTTPUpload& upload) override {
+ if (canUpload(requestUri))
+ _ufn();
+ }
+
+protected:
+ ESP32WebServer::THandlerFunction _fn;
+ ESP32WebServer::THandlerFunction _ufn;
+ String _uri;
+ HTTPMethod _method;
+};
+
+
+
+#endif //REQUESTHANDLERSIMPL_H
diff --git a/libraries/Nefry/library.properties b/libraries/Nefry/library.properties
index 5b2fb15e436..ff6f51f356d 100644
--- a/libraries/Nefry/library.properties
+++ b/libraries/Nefry/library.properties
@@ -1,5 +1,5 @@
name=Nefry
-version=0.6.1
+version=0.6.2
author=Nefry community
maintainer=
sentence=nefry.
diff --git a/package/package_esp32_index.template.json b/package/package_esp32_index.template.json
index 204044dd103..21940bc50e6 100644
--- a/package/package_esp32_index.template.json
+++ b/package/package_esp32_index.template.json
@@ -3,7 +3,7 @@
{
"name": "esp32",
"maintainer": "Espressif Systems",
- "websiteURL": "https://github.com/espressif/esp32-arduino",
+ "websiteURL": "https://github.com/espressif/arduino-esp32",
"email": "hristo@espressif.com",
"help": {
"online": "http://esp32.com"
diff --git a/release note.md b/release note.md
index 30c9cb96152..af28c17994b 100644
--- a/release note.md
+++ b/release note.md
@@ -1,5 +1,19 @@
# このノートはNefry(ESP32版)のリリースノートになります。
+## 0.6.2
+
+NefryのWeb関連機能の修正とDNSの追加、それに伴う起動シークエンスの変更
+
+新規機能
+
+- DNS対応
+- CaptivePortal対応
+- webserver更新
+
+バグフィックス
+
+- 起動シークエンスの変更
+
## 0.6.1
IFTTTライブラリー追加とバグフィックス対応
diff --git a/tools/partitions/default.csv b/tools/partitions/default.csv
index 92b29eeba02..b0f4c20b097 100644
--- a/tools/partitions/default.csv
+++ b/tools/partitions/default.csv
@@ -1,6 +1,6 @@
-# Name, Type, SubType, Offset, Size, Flags
-nvs, data, nvs, 0x9000, 0x5000
-otadata, data, ota, 0xe000, 0x2000
+# Name, Type, SubType, Offset, Size, Flags
+nvs, data, nvs, 0x9000, 0x5000,
+otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 1M,
-app1, app, ota_1, , 1M,
-spiffs, data, spiffs, , 0x1F0000,
+app1, app, ota_1, 0x110000,1M,
+spiffs, data, spiffs, 0x210000,0x1F0000,
diff --git a/variants/esp32/pins_arduino.h b/variants/esp32/pins_arduino.h
index d50715e5c91..d852bb03452 100644
--- a/variants/esp32/pins_arduino.h
+++ b/variants/esp32/pins_arduino.h
@@ -53,4 +53,6 @@ static const uint8_t T9 = 32;
static const uint8_t DAC1 = 25;
static const uint8_t DAC2 = 26;
+static const uint8_t boardId = 0;//ESP32
+
#endif /* Pins_Arduino_h */
diff --git a/variants/nefrybt/pins_arduino.h b/variants/nefrybt/pins_arduino.h
index 63375183afd..dfb29606ec6 100644
--- a/variants/nefrybt/pins_arduino.h
+++ b/variants/nefrybt/pins_arduino.h
@@ -46,4 +46,6 @@ static const uint8_t T4 = 13;
static const uint8_t DAC1 = 25;
static const uint8_t DAC2 = 26;
+static const uint8_t boardId = 1;//Nefry BT
+
#endif /* Pins_Arduino_h */
diff --git a/variants/onehorse32dev/pins_arduino.h b/variants/onehorse32dev/pins_arduino.h
new file mode 100644
index 00000000000..daa2d8cd6fd
--- /dev/null
+++ b/variants/onehorse32dev/pins_arduino.h
@@ -0,0 +1,59 @@
+#ifndef Pins_Arduino_h
+#define Pins_Arduino_h
+
+#include
+
+#define EXTERNAL_NUM_INTERRUPTS 16
+#define NUM_DIGITAL_PINS 40
+#define NUM_ANALOG_INPUTS 16
+
+#define analogInputToDigitalPin(p) (((p)<20)?(esp32_adc2gpio[(p)]):-1)
+#define digitalPinToInterrupt(p) (((p)<40)?(p):-1)
+#define digitalPinHasPWM(p) (p < 34)
+
+static const uint8_t LED_BUILTIN = 5;
+#define BUILTIN_LED LED_BUILTIN // backward compatibility
+
+static const uint8_t KEY_BUILTIN = 0;
+
+static const uint8_t TX = 1;
+static const uint8_t RX = 3;
+
+static const uint8_t SDA = 21;
+static const uint8_t SCL = 22;
+
+static const uint8_t SS = 5;
+static const uint8_t MOSI = 23;
+static const uint8_t MISO = 19;
+static const uint8_t SCK = 18;
+
+static const uint8_t A0 = 36;
+static const uint8_t A1 = 37;
+static const uint8_t A2 = 38;
+static const uint8_t A3 = 39;
+static const uint8_t A6 = 34;
+static const uint8_t A7 = 35;
+static const uint8_t A10 = 4;
+static const uint8_t A11 = 0;
+static const uint8_t A12 = 2;
+static const uint8_t A13 = 15;
+static const uint8_t A14 = 13;
+static const uint8_t A15 = 12;
+static const uint8_t A16 = 14;
+static const uint8_t A17 = 27;
+static const uint8_t A18 = 25;
+static const uint8_t A19 = 26;
+
+static const uint8_t T0 = 4;
+static const uint8_t T1 = 0;
+static const uint8_t T2 = 2;
+static const uint8_t T3 = 15;
+static const uint8_t T4 = 13;
+static const uint8_t T5 = 12;
+static const uint8_t T6 = 14;
+static const uint8_t T7 = 27;
+
+static const uint8_t DAC1 = 25;
+static const uint8_t DAC2 = 26;
+
+#endif /* Pins_Arduino_h */