From 4f659b75634a60399aa969bc56b50c0fcd467ba8 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Wed, 7 Oct 2020 22:02:53 -0700 Subject: [PATCH 01/16] Initial check in of HTTPS server for #452 This switches from the espressif web server to esp32_https_server. Both HTTPS and HTTP have been migrated. On board SSL key generation. --- src/PowerFSM.cpp | 2 + src/main.cpp | 1 + src/meshwifi/meshhttp.cpp | 349 ++++++++++++++++++++++++++------------ src/meshwifi/meshhttp.h | 2 + src/meshwifi/meshwifi.cpp | 6 +- 5 files changed, 253 insertions(+), 107 deletions(-) diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 14f7b996..5acc785e 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -118,6 +118,8 @@ static void powerEnter() { screen.setOn(true); setBluetoothEnable(true); + setCPUFast(true); // Set CPU to 240mhz when we're plugged in to wall power. + DEBUG_MSG("PowerFSM - powerEnter(true)\n"); } static void onEnter() diff --git a/src/main.cpp b/src/main.cpp index 37e9077d..32076a0d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -336,6 +336,7 @@ void setup() // Initialize Wifi initWifi(); + if (!rIf) recordCriticalError(ErrNoRadio); diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index 9106ab08..eb4fca95 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -6,29 +6,46 @@ #include #include -WebServer webserver(80); +// Persistant Data Storage +#include +Preferences prefs; -// Maximum number of messages for chat history. Don't make this too big -- it'll use a -// lot of memory! -const uint16_t maxMessages = 50; +/* + Including the esp32_https_server library will trigger a compile time error. I've + tracked it down to a reoccurrance of this bug: + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57824 + The work around is described here: + https://forums.xilinx.com/t5/Embedded-Development-Tools/Error-with-Standard-Libaries-in-Zynq/td-p/450032 -struct message_t { - char sender[10]; - char message[250]; - int32_t gpsLat; - int32_t gpsLong; - uint32_t time; - bool fromMe; -}; + Long story short is we need "#undef str" before including the esp32_https_server. + - Jm Casler (jm@casler.org) Oct 2020 +*/ +#undef str -struct messages_t { - message_t history[maxMessages]; -}; +// Includes for the https server +// https://github.com/fhessel/esp32_https_server +#include +#include +#include +#include +#include -messages_t messages_history; +// The HTTPS Server comes in a separate namespace. For easier use, include it here. +using namespace httpsserver; -String something = ""; -String sender = ""; +SSLCert *cert; +HTTPSServer *secureServer; +HTTPServer *insecureServer; + +// Declare some handler functions for the various URLs on the server +void handleStyleCSS(HTTPRequest *req, HTTPResponse *res); +void handleJSONChatHistoryDummy(HTTPRequest *req, HTTPResponse *res); +void handleHotspot(HTTPRequest *req, HTTPResponse *res); +void handleRoot(HTTPRequest *req, HTTPResponse *res); +void handle404(HTTPRequest *req, HTTPResponse *res); + +bool isWebServerReady = 0; +bool isCertReady = 0; void handleWebResponse() { @@ -36,82 +53,196 @@ void handleWebResponse() return; } - // We're going to handle the DNS responder here so it - // will be ignored by the NRF boards. - handleDNSResponse(); + if (isWebServerReady) { + // We're going to handle the DNS responder here so it + // will be ignored by the NRF boards. + handleDNSResponse(); - webserver.handleClient(); + secureServer->loop(); + insecureServer->loop(); + } +} + +void taskCreateCert(void *parameter) +{ + + prefs.begin("MeshtasticHTTPS", false); + + // Delete the saved certs + if (0) { + DEBUG_MSG("Deleting any saved SSL keys ...\n"); + // prefs.clear(); + prefs.remove("PK"); + prefs.remove("cert"); + } + + size_t pkLen = prefs.getBytesLength("PK"); + size_t certLen = prefs.getBytesLength("cert"); + + DEBUG_MSG("Checking if we have a previously saved SSL Certificate.\n"); + + if (pkLen && certLen) { + DEBUG_MSG("Existing SSL Certificate found!\n"); + } else { + DEBUG_MSG("Creating the certificate. This may take a while. Please wait...\n"); + + cert = new SSLCert(); + //disableCore1WDT(); + int createCertResult = createSelfSignedCert(*cert, KEYSIZE_2048, "CN=meshtastic.local,O=Meshtastic,C=US", + "20190101000000", "20300101000000"); + //enableCore1WDT(); + + if (createCertResult != 0) { + DEBUG_MSG("Creating the certificate failed\n"); + + // Serial.printf("Creating the certificate failed. Error Code = 0x%02X, check SSLCert.hpp for details", + // createCertResult); + // while (true) + // delay(500); + } else { + DEBUG_MSG("Creating the certificate was successful\n"); + + DEBUG_MSG("Created Private Key: %d Bytes\n", cert->getPKLength()); + // for (int i = 0; i < cert->getPKLength(); i++) + // Serial.print(cert->getPKData()[i], HEX); + // Serial.println(); + + DEBUG_MSG("Created Certificate: %d Bytes\n", cert->getCertLength()); + // for (int i = 0; i < cert->getCertLength(); i++) + // Serial.print(cert->getCertData()[i], HEX); + // Serial.println(); + + prefs.putBytes("PK", (uint8_t *)cert->getPKData(), cert->getPKLength()); + prefs.putBytes("cert", (uint8_t *)cert->getCertData(), cert->getCertLength()); + } + } + + isCertReady = 1; + vTaskDelete(NULL); +} + +void createSSLCert() +{ + + if (isWifiAvailable() == 0) { + return; + } + + // Create a new process just to handle creating the cert. + // This is a workaround for Bug: https://github.com/fhessel/esp32_https_server/issues/48 + // jm@casler.org (Oct 2020) + xTaskCreate(taskCreateCert, /* Task function. */ + "createCert", /* String with name of task. */ + 16384, /* Stack size in bytes. */ + NULL, /* Parameter passed as input of the task */ + 16, /* Priority of the task. */ + NULL); /* Task handle. */ + + DEBUG_MSG("Waiting for SSL Cert to be generated.\n"); + if (isCertReady) { + DEBUG_MSG(".\n"); + delayMicroseconds(1000); + } + DEBUG_MSG("SSL Cert Ready!\n"); } void initWebServer() { - webserver.onNotFound(handleNotFound); - webserver.on("/json/chat/send/channel", handleJSONChatHistory); - webserver.on("/json/chat/send/user", handleJSONChatHistory); - webserver.on("/json/chat/history/channel", handleJSONChatHistory); - webserver.on("/json/chat/history/dummy", handleJSONChatHistoryDummy); - webserver.on("/json/chat/history/user", handleJSONChatHistory); - webserver.on("/json/stats", handleJSONChatHistory); - webserver.on("/hotspot-detect.html", handleHotspot); - webserver.on("/css/style.css", handleStyleCSS); - webserver.on("/scripts/script.js", handleScriptsScriptJS); - webserver.on("/", handleRoot); - webserver.begin(); -} + DEBUG_MSG("Initializing Web Server ...\n"); -void handleJSONChatHistory() -{ - int i; + prefs.begin("MeshtasticHTTPS", false); - String out = ""; - out += "{\n"; - out += " \"data\" : {\n"; - out += " \"chat\" : "; - out += "["; - out += "\"" + sender + "\""; - out += ","; - out += "\"" + something + "\""; - out += "]\n"; + size_t pkLen = prefs.getBytesLength("PK"); + size_t certLen = prefs.getBytesLength("cert"); - for (i = 0; i < maxMessages; i++) { - out += "["; - out += "\"" + String(messages_history.history[i].sender) + "\""; - out += ","; - out += "\"" + String(messages_history.history[i].message) + "\""; - out += "]\n"; + DEBUG_MSG("Checking if we have a previously saved SSL Certificate.\n"); + + if (pkLen && certLen) { + + uint8_t *pkBuffer = new uint8_t[pkLen]; + prefs.getBytes("PK", pkBuffer, pkLen); + + uint8_t *certBuffer = new uint8_t[certLen]; + prefs.getBytes("cert", certBuffer, certLen); + + cert = new SSLCert(certBuffer, certLen, pkBuffer, pkLen); + + DEBUG_MSG("Retrieved Private Key: %d Bytes\n", cert->getPKLength()); + // DEBUG_MSG("Retrieved Private Key: " + String(cert->getPKLength()) + " Bytes"); + // for (int i = 0; i < cert->getPKLength(); i++) + // Serial.print(cert->getPKData()[i], HEX); + // Serial.println(); + + DEBUG_MSG("Retrieved Certificate: %d Bytes\n", cert->getCertLength()); + // for (int i = 0; i < cert->getCertLength(); i++) + // Serial.print(cert->getCertData()[i], HEX); + // Serial.println(); + } else { + DEBUG_MSG("Web Server started without SSL keys! How did this happen?\n"); } - out += "\n"; - out += " }\n"; - out += "}\n"; + // We can now use the new certificate to setup our server as usual. + secureServer = new HTTPSServer(cert); + insecureServer = new HTTPServer(); - webserver.send(200, "application/json", out); - return; + // For every resource available on the server, we need to create a ResourceNode + // The ResourceNode links URL and HTTP method to a handler function + + ResourceNode *nodeCSS = new ResourceNode("/css/style.css", "GET", &handleStyleCSS); + ResourceNode *nodeJS = new ResourceNode("/scripts/script.js", "GET", &handleJSONChatHistoryDummy); + ResourceNode *nodeHotspot = new ResourceNode("/hotspot-detect.html", "GET", &handleHotspot); + ResourceNode *nodeRoot = new ResourceNode("/", "GET", &handleRoot); + ResourceNode *node404 = new ResourceNode("", "GET", &handle404); + + // Secure nodes + secureServer->registerNode(nodeCSS); + secureServer->registerNode(nodeJS); + secureServer->registerNode(nodeHotspot); + secureServer->registerNode(nodeRoot); + secureServer->setDefaultNode(node404); + + // Insecure nodes + insecureServer->registerNode(nodeCSS); + insecureServer->registerNode(nodeJS); + insecureServer->registerNode(nodeHotspot); + insecureServer->registerNode(nodeRoot); + insecureServer->setDefaultNode(node404); + + DEBUG_MSG("Starting Web Server...\n"); + secureServer->start(); + insecureServer->start(); + if (secureServer->isRunning() && insecureServer->isRunning()) { + DEBUG_MSG("Web Server Ready\n"); + isWebServerReady = 1; + } } -void handleNotFound() +void handle404(HTTPRequest *req, HTTPResponse *res) { - String message = ""; - message += "File Not Found\n\n"; - message += "URI: "; - message += webserver.uri(); - message += "\nMethod: "; - message += (webserver.method() == HTTP_GET) ? "GET" : "POST"; - message += "\nArguments: "; - message += webserver.args(); - message += "\n"; - for (uint8_t i = 0; i < webserver.args(); i++) { - message += " " + webserver.argName(i) + ": " + webserver.arg(i) + "\n"; - } - Serial.println(message); - webserver.send(404, "text/plain", message); + // Discard request body, if we received any + // We do this, as this is the default node and may also server POST/PUT requests + req->discardRequestBody(); + + // Set the response status + res->setStatusCode(404); + res->setStatusText("Not Found"); + + // Set content type of the response + res->setHeader("Content-Type", "text/html"); + + // Write a tiny HTTP page + res->println(""); + res->println(""); + res->println("Not Found"); + res->println("

404 Not Found

The requested resource was not found on this server.

"); + res->println(""); } /* This supports the Apple Captive Network Assistant (CNA) Portal */ -void handleHotspot() +void handleHotspot(HTTPRequest *req, HTTPResponse *res) { DEBUG_MSG("Hotspot Request\n"); @@ -120,25 +251,14 @@ void handleHotspot() otherwise iOS will have trouble detecting that the connection to the SoftAP worked. */ - String out = ""; - // out += "Success\n"; - out += "\n"; - webserver.send(200, "text/html", out); - return; -} + // Status code is 200 OK by default. + // We want to deliver a simple HTML page, so we send a corresponding content type: + res->setHeader("Content-Type", "text/html"); -void notifyWebUI() -{ - DEBUG_MSG("************ Got a message! ************\n"); - MeshPacket &mp = devicestate.rx_text_message; - NodeInfo *node = nodeDB.getNode(mp.from); - sender = (node && node->has_user) ? node->user.long_name : "???"; - - static char tempBuf[256]; // mesh.options says this is MeshPacket.encrypted max_size - assert(mp.decoded.which_payload == SubPacket_data_tag); - snprintf(tempBuf, sizeof(tempBuf), "%s", mp.decoded.data.payload.bytes); - - something = tempBuf; + // The response implements the Print interface, so you can use it just like + // you would write to Serial etc. + res->println(""); + res->println("\n"); } /* @@ -146,7 +266,7 @@ void notifyWebUI() https://tomeko.net/online_tools/cpp_text_escape.php?lang=en */ -void handleRoot() +void handleRoot(HTTPRequest *req, HTTPResponse *res) { String out = ""; @@ -223,11 +343,17 @@ void handleRoot() "\n" "\n" ""; - webserver.send(200, "text/html", out); - return; + + // Status code is 200 OK by default. + // We want to deliver a simple HTML page, so we send a corresponding content type: + res->setHeader("Content-Type", "text/html"); + + // The response implements the Print interface, so you can use it just like + // you would write to Serial etc. + res->print(out); } -void handleStyleCSS() +void handleStyleCSS(HTTPRequest *req, HTTPResponse *res) { String out = ""; @@ -510,11 +636,16 @@ void handleStyleCSS() " height: 0;\n" "}"; - webserver.send(200, "text/css", out); - return; + // Status code is 200 OK by default. + // We want to deliver a simple HTML page, so we send a corresponding content type: + res->setHeader("Content-Type", "text/css"); + + // The response implements the Print interface, so you can use it just like + // you would write to Serial etc. + res->print(out); } -void handleScriptsScriptJS() +void handleScriptsScriptJS(HTTPRequest *req, HTTPResponse *res) { String out = ""; out += "String.prototype.toHHMMSS = function () {\n" @@ -664,11 +795,16 @@ void handleScriptsScriptJS() "//\tsetTimeout(scrollHistory(),500);\n" "// }"; - webserver.send(200, "text/javascript", out); - return; + // Status code is 200 OK by default. + // We want to deliver a simple HTML page, so we send a corresponding content type: + res->setHeader("Content-Type", "text/html"); + + // The response implements the Print interface, so you can use it just like + // you would write to Serial etc. + res->print(out); } -void handleJSONChatHistoryDummy() +void handleJSONChatHistoryDummy(HTTPRequest *req, HTTPResponse *res) { String out = ""; out += "{\n" @@ -788,6 +924,11 @@ void handleJSONChatHistoryDummy() "\t}\n" "}"; - webserver.send(200, "application/json", out); - return; + // Status code is 200 OK by default. + // We want to deliver a simple HTML page, so we send a corresponding content type: + res->setHeader("Content-Type", "application/json"); + + // The response implements the Print interface, so you can use it just like + // you would write to Serial etc. + res->print(out); } \ No newline at end of file diff --git a/src/meshwifi/meshhttp.h b/src/meshwifi/meshhttp.h index 42c6644b..eeddfe9f 100644 --- a/src/meshwifi/meshhttp.h +++ b/src/meshwifi/meshhttp.h @@ -4,6 +4,8 @@ #include void initWebServer(); +void createSSLCert(); + void handleNotFound(); diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index b7a8dace..ed5f5dfc 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -29,9 +29,6 @@ bool isWifiAvailable() // strcpy(radioConfig.preferences.wifi_password, ""); if (*wifiName && *wifiPsw) { - - // Once every 10 seconds, try to reconnect. - return 1; } else { return 0; @@ -64,6 +61,9 @@ void initWifi() return; } + createSSLCert(); + + if (radioConfig.has_preferences) { const char *wifiName = radioConfig.preferences.wifi_ssid; const char *wifiPsw = radioConfig.preferences.wifi_password; From 6d178ebc9150ea96f8df53c44308f5d9593c0580 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Wed, 7 Oct 2020 22:18:46 -0700 Subject: [PATCH 02/16] Added esp32_https_server to the meshtastic project --- platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio.ini b/platformio.ini index b48dc393..03420d96 100644 --- a/platformio.ini +++ b/platformio.ini @@ -66,6 +66,7 @@ lib_deps = https://github.com/meshtastic/RadioLib.git#1083c2e76f9906c5f80dfec726facebf8413eef0 https://github.com/meshtastic/TinyGPSPlus.git https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460 + https://github.com/meshtastic/esp32_https_server.git Wire ; explicitly needed here because the AXP202 library forgets to add it SPI From db8faa9fafe6a4c523da12f6a19af00463b6b233 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Fri, 9 Oct 2020 23:07:37 -0700 Subject: [PATCH 03/16] added powerExit --- src/PowerFSM.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index a464c833..ba16be4d 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -125,7 +125,13 @@ static void powerEnter() screen.setOn(true); setBluetoothEnable(true); setCPUFast(true); // Set CPU to 240mhz when we're plugged in to wall power. - DEBUG_MSG("PowerFSM - powerEnter(true)\n"); +} + +static void powerExit() +{ + screen.setOn(true); + setBluetoothEnable(true); + setCPUFast(false); // Set CPU to 80mhz when we're plugged in to wall power. } static void onEnter() @@ -159,6 +165,8 @@ State stateSERIAL(serialEnter, NULL, NULL, "SERIAL"); State stateBOOT(bootEnter, NULL, NULL, "BOOT"); State stateON(onEnter, NULL, NULL, "ON"); State statePOWER(powerEnter, NULL, NULL, "POWER"); +State stateUNPLUG(powerExit, NULL, NULL, "UNPLUG"); + Fsm powerFSM(&stateBOOT); void PowerFSM_setup() @@ -224,6 +232,7 @@ void PowerFSM_setup() powerFSM.add_transition(&stateNB, &statePOWER, EVENT_POWER_CONNECTED, NULL, "power connect"); powerFSM.add_transition(&stateDARK, &statePOWER, EVENT_POWER_CONNECTED, NULL, "power connect"); powerFSM.add_transition(&stateON, &statePOWER, EVENT_POWER_CONNECTED, NULL, "power connect"); + powerFSM.add_transition(&statePOWER, &stateUNPLUG, EVENT_POWER_DISCONNECTED, NULL, "power disconnected"); } powerFSM.add_transition(&statePOWER, &stateON, EVENT_POWER_DISCONNECTED, NULL, "power disconnected"); From 5b777219be6e04292d02b3671d8d7f00ae0e2d2b Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sat, 10 Oct 2020 17:59:32 -0700 Subject: [PATCH 04/16] Enable the RX LNA #466 Enabling the RX LNA --- src/mesh/SX1262Interface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mesh/SX1262Interface.cpp b/src/mesh/SX1262Interface.cpp index b17acd9f..9d38f122 100644 --- a/src/mesh/SX1262Interface.cpp +++ b/src/mesh/SX1262Interface.cpp @@ -82,8 +82,8 @@ bool SX1262Interface::reconfigure() assert(err == ERR_NONE); // Hmm - seems to lower SNR when the signal levels are high. Leaving off for now... - // err = lora.setRxGain(true); - // assert(err == ERR_NONE); + err = lora.setRxGain(true); + assert(err == ERR_NONE); err = lora.setSyncWord(syncWord); assert(err == ERR_NONE); From b17a8d7a6acb118b605b381679ad514c109a1890 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sat, 10 Oct 2020 21:54:27 -0700 Subject: [PATCH 05/16] Removed powerExit -- it wasn't working --- src/PowerFSM.cpp | 10 +--------- src/graphics/Screen.cpp | 4 ++++ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index ba16be4d..63d05a5a 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -127,13 +127,6 @@ static void powerEnter() setCPUFast(true); // Set CPU to 240mhz when we're plugged in to wall power. } -static void powerExit() -{ - screen.setOn(true); - setBluetoothEnable(true); - setCPUFast(false); // Set CPU to 80mhz when we're plugged in to wall power. -} - static void onEnter() { screen.setOn(true); @@ -148,6 +141,7 @@ static void onEnter() service.sendNetworkPing(displayedNodeNum, true); // Refresh the currently displayed node lastPingMs = now; } + } static void screenPress() @@ -165,7 +159,6 @@ State stateSERIAL(serialEnter, NULL, NULL, "SERIAL"); State stateBOOT(bootEnter, NULL, NULL, "BOOT"); State stateON(onEnter, NULL, NULL, "ON"); State statePOWER(powerEnter, NULL, NULL, "POWER"); -State stateUNPLUG(powerExit, NULL, NULL, "UNPLUG"); Fsm powerFSM(&stateBOOT); @@ -232,7 +225,6 @@ void PowerFSM_setup() powerFSM.add_transition(&stateNB, &statePOWER, EVENT_POWER_CONNECTED, NULL, "power connect"); powerFSM.add_transition(&stateDARK, &statePOWER, EVENT_POWER_CONNECTED, NULL, "power connect"); powerFSM.add_transition(&stateON, &statePOWER, EVENT_POWER_CONNECTED, NULL, "power connect"); - powerFSM.add_transition(&statePOWER, &stateUNPLUG, EVENT_POWER_DISCONNECTED, NULL, "power disconnected"); } powerFSM.add_transition(&statePOWER, &stateON, EVENT_POWER_DISCONNECTED, NULL, "power disconnected"); diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 2ea03c63..28496201 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1026,6 +1026,10 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat String(days) + "d " + (hours < 10 ? "0" : "") + String(hours) + ":" + (minutes < 10 ? "0" : "") + String(minutes) + ":" + (seconds < 10 ? "0" : "") + String(seconds)); + // Show CPU Frequency. + display->drawString(x + SCREEN_WIDTH - display->getStringWidth("CPU " + String(getCpuFrequencyMhz()) + "MHz"), y + FONT_HEIGHT * 1, + "CPU " + String(getCpuFrequencyMhz()) + "MHz"); + // Line 3 drawGPSAltitude(display, x, y + FONT_HEIGHT * 2, gpsStatus); From d39cc3d57bf99b68aaf7e713620ccea9c33fbf78 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sat, 10 Oct 2020 22:06:56 -0700 Subject: [PATCH 06/16] Checking if ESP32 for the frequency display --- src/graphics/Screen.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 28496201..2fcb99b9 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1026,9 +1026,11 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat String(days) + "d " + (hours < 10 ? "0" : "") + String(hours) + ":" + (minutes < 10 ? "0" : "") + String(minutes) + ":" + (seconds < 10 ? "0" : "") + String(seconds)); +#ifndef NO_ESP32 // Show CPU Frequency. display->drawString(x + SCREEN_WIDTH - display->getStringWidth("CPU " + String(getCpuFrequencyMhz()) + "MHz"), y + FONT_HEIGHT * 1, "CPU " + String(getCpuFrequencyMhz()) + "MHz"); +#endif // Line 3 drawGPSAltitude(display, x, y + FONT_HEIGHT * 2, gpsStatus); From b9ce75b09c19ab079b357e9c05f2cbade87963a1 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Mon, 12 Oct 2020 09:03:04 +0800 Subject: [PATCH 07/16] fix build for linux (by moving esp32 specific lib to esp32 tree) --- platformio.ini | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 366441be..ee362235 100644 --- a/platformio.ini +++ b/platformio.ini @@ -67,7 +67,6 @@ lib_deps = https://github.com/meshtastic/RadioLib.git#8657380241bce681c33aab46598bbf13b11f876c https://github.com/meshtastic/TinyGPSPlus.git https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460 - https://github.com/meshtastic/esp32_https_server.git Wire ; explicitly needed here because the AXP202 library forgets to add it SPI https://github.com/geeksville/ArduinoThread.git#333ffd09b596977c217ba25da4258f588b462ac6 @@ -96,6 +95,9 @@ build_flags = ${arduino_base.build_flags} -Wall -Wextra -Isrc/esp32 -Isrc/esp32-mfix-esp32-psram-cache-issue -lnimble -std=c++11 -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG -DAXP_DEBUG_PORT=Serial +lib_deps = + ${arduino_base.lib_deps} + https://github.com/meshtastic/esp32_https_server.git # Hmm - this doesn't work yet # board_build.ldscript = linker/esp32.extram.bss.ld lib_ignore = segger_rtt From 3d3f7869d4548856a662fee9ec70446398cd409c Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sun, 11 Oct 2020 20:38:09 -0700 Subject: [PATCH 08/16] Increase CPU frequency on HTTPS requests. Clock back down after a period of time. --- src/PowerFSM.cpp | 1 - src/meshwifi/meshhttp.cpp | 76 +++++++++++++++++++++++++++++++++++++-- src/meshwifi/meshhttp.h | 19 ++++++++-- src/meshwifi/meshwifi.cpp | 2 +- 4 files changed, 91 insertions(+), 7 deletions(-) diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 79d5af4d..e6cc3738 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -124,7 +124,6 @@ static void powerEnter() { screen->setOn(true); setBluetoothEnable(true); - setCPUFast(true); // Set CPU to 240mhz when we're plugged in to wall power. } static void onEnter() diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index eb4fca95..49777913 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -3,6 +3,7 @@ #include "configuration.h" #include "main.h" #include "meshwifi/meshwifi.h" +#include "sleep.h" #include #include @@ -30,6 +31,8 @@ Preferences prefs; #include #include +#define HEADER_LEN 4 + // The HTTPS Server comes in a separate namespace. For easier use, include it here. using namespace httpsserver; @@ -37,16 +40,25 @@ SSLCert *cert; HTTPSServer *secureServer; HTTPServer *insecureServer; +// Our API to handle messages to and from the radio. +httpAPI webAPI; + // Declare some handler functions for the various URLs on the server +void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res); +void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res); void handleStyleCSS(HTTPRequest *req, HTTPResponse *res); void handleJSONChatHistoryDummy(HTTPRequest *req, HTTPResponse *res); void handleHotspot(HTTPRequest *req, HTTPResponse *res); void handleRoot(HTTPRequest *req, HTTPResponse *res); void handle404(HTTPRequest *req, HTTPResponse *res); +void middlewareLogging(HTTPRequest *req, HTTPResponse *res, std::function next); + bool isWebServerReady = 0; bool isCertReady = 0; +uint32_t timeSpeedUp = 0; + void handleWebResponse() { if (isWifiAvailable() == 0) { @@ -61,6 +73,14 @@ void handleWebResponse() secureServer->loop(); insecureServer->loop(); } + + // Slow down the CPU if we have not received a request within the last + // 2 minutes. + if (millis () - timeSpeedUp >= (2 * 60 * 1000)) { + setCPUFast(false); // Set CPU to 80mhz + timeSpeedUp = millis(); + } + } void taskCreateCert(void *parameter) @@ -87,10 +107,10 @@ void taskCreateCert(void *parameter) DEBUG_MSG("Creating the certificate. This may take a while. Please wait...\n"); cert = new SSLCert(); - //disableCore1WDT(); + // disableCore1WDT(); int createCertResult = createSelfSignedCert(*cert, KEYSIZE_2048, "CN=meshtastic.local,O=Meshtastic,C=US", "20190101000000", "20300101000000"); - //enableCore1WDT(); + // enableCore1WDT(); if (createCertResult != 0) { DEBUG_MSG("Creating the certificate failed\n"); @@ -188,6 +208,8 @@ void initWebServer() // For every resource available on the server, we need to create a ResourceNode // The ResourceNode links URL and HTTP method to a handler function + ResourceNode *nodeAPIv1ToRadio = new ResourceNode("/api/v1/toradio", "GET", &handleAPIv1ToRadio); + ResourceNode *nodeAPIv1FromRadio = new ResourceNode("/api/v1/fromradio", "GET", &handleAPIv1FromRadio); ResourceNode *nodeCSS = new ResourceNode("/css/style.css", "GET", &handleStyleCSS); ResourceNode *nodeJS = new ResourceNode("/scripts/script.js", "GET", &handleJSONChatHistoryDummy); ResourceNode *nodeHotspot = new ResourceNode("/hotspot-detect.html", "GET", &handleHotspot); @@ -195,13 +217,19 @@ void initWebServer() ResourceNode *node404 = new ResourceNode("", "GET", &handle404); // Secure nodes + secureServer->registerNode(nodeAPIv1ToRadio); + secureServer->registerNode(nodeAPIv1FromRadio); secureServer->registerNode(nodeCSS); secureServer->registerNode(nodeJS); secureServer->registerNode(nodeHotspot); secureServer->registerNode(nodeRoot); secureServer->setDefaultNode(node404); + secureServer->addMiddleware(&middlewareLogging); + // Insecure nodes + insecureServer->registerNode(nodeAPIv1ToRadio); + insecureServer->registerNode(nodeAPIv1FromRadio); insecureServer->registerNode(nodeCSS); insecureServer->registerNode(nodeJS); insecureServer->registerNode(nodeHotspot); @@ -217,6 +245,16 @@ void initWebServer() } } +void middlewareLogging(HTTPRequest *req, HTTPResponse *res, std::function next) +{ + // We want to print the response status, so we need to call next() first. + next(); + + setCPUFast(true); // Set CPU to 240mhz when we're plugged in to wall power. + timeSpeedUp = millis(); + +} + void handle404(HTTPRequest *req, HTTPResponse *res) { @@ -261,6 +299,40 @@ void handleHotspot(HTTPRequest *req, HTTPResponse *res) res->println("\n"); } +void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res) +{ + DEBUG_MSG("+++++++++++++++ webAPI handleAPIv1FromRadio\n"); + + /* + http://10.10.30.198/api/v1/fromradio + + */ + + // Status code is 200 OK by default. + // We want to deliver a simple HTML page, so we send a corresponding content type: + res->setHeader("Content-Type", "application/x-protobuf"); + + uint8_t txBuf[MAX_STREAM_BUF_SIZE]; + + uint32_t len = webAPI.getFromRadio(txBuf + HEADER_LEN); + + res->write(txBuf, len); + DEBUG_MSG("--------------- webAPI handleAPIv1FromRadio, len %d\n", len); +} + +void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res) +{ + DEBUG_MSG("webAPI handleAPIv1ToRadio\n"); + + // Status code is 200 OK by default. + // We want to deliver a simple HTML page, so we send a corresponding content type: + res->setHeader("Content-Type", "application/x-protobuf"); + + // The response implements the Print interface, so you can use it just like + // you would write to Serial etc. + res->print(""); +} + /* To convert text to c strings: diff --git a/src/meshwifi/meshhttp.h b/src/meshwifi/meshhttp.h index eeddfe9f..42bb1d3b 100644 --- a/src/meshwifi/meshhttp.h +++ b/src/meshwifi/meshhttp.h @@ -2,11 +2,11 @@ #include #include +#include "PhoneAPI.h" void initWebServer(); void createSSLCert(); - void handleNotFound(); void handleWebResponse(); @@ -17,8 +17,21 @@ void notifyWebUI(); void handleHotspot(); - void handleStyleCSS(); void handleRoot(); void handleScriptsScriptJS(); -void handleJSONChatHistoryDummy(); \ No newline at end of file +void handleJSONChatHistoryDummy(); + +class httpAPI : public PhoneAPI +{ + +public: + // Nothing here yet + +private: + // Nothing here yet + +protected: + // Nothing here yet + +}; \ No newline at end of file diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index 6ba32df8..3026b13f 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -17,7 +17,7 @@ static WiFiServerPort *apiPort; uint8_t wifiDisconnectReason = 0; -// Stores the last 4 of our hardware ID, to make finding the device for pairing easier +// Stores our hostname static char ourHost[16]; bool isWifiAvailable() From 10008d4eef14e638aaf1465f7531d1e7aadc292d Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sun, 11 Oct 2020 21:19:22 -0700 Subject: [PATCH 09/16] fix merge conflict --- bin/version.sh | 2 +- platformio.ini | 2 +- src/Power.cpp | 61 +++++++------- src/PowerFSM.cpp | 12 ++- src/PowerFSM.h | 2 +- src/concurrency/InterruptableDelay.cpp | 22 ++--- src/graphics/Screen.h | 2 +- src/main.cpp | 109 +++++++++++++++---------- 8 files changed, 118 insertions(+), 94 deletions(-) diff --git a/bin/version.sh b/bin/version.sh index feeef016..ef346111 100644 --- a/bin/version.sh +++ b/bin/version.sh @@ -1,3 +1,3 @@ -export VERSION=1.1.3 \ No newline at end of file +export VERSION=1.1.4 \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index ee362235..3b7c6abb 100644 --- a/platformio.ini +++ b/platformio.ini @@ -60,7 +60,7 @@ debug_tool = jlink lib_deps = https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306 - 1260 ; OneButton library for non-blocking button debounce + https://github.com/geeksville/OneButton.git ; OneButton library for non-blocking button debounce 1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib https://github.com/meshtastic/arduino-fsm.git#2f106146071fc7bc620e1e8d4b88dc4e0266ce39 https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git#31015a55e630a2df77d9d714669c621a5bf355ad diff --git a/src/Power.cpp b/src/Power.cpp index 162047fa..12a63811 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -138,38 +138,39 @@ int32_t Power::runOnce() { readPowerStatus(); -#ifdef PMU_IRQ - if (pmu_irq) { - pmu_irq = false; - axp.readIRQ(); +#ifdef TBEAM_V10 + // WE no longer use the IRQ line to wake the CPU (due to false wakes from sleep), but we do poll + // the IRQ status by reading the registers over I2C + axp.readIRQ(); - DEBUG_MSG("pmu irq!\n"); - - if (axp.isChargingIRQ()) { - DEBUG_MSG("Battery start charging\n"); - } - if (axp.isChargingDoneIRQ()) { - DEBUG_MSG("Battery fully charged\n"); - } - if (axp.isVbusRemoveIRQ()) { - DEBUG_MSG("USB unplugged\n"); - powerFSM.trigger(EVENT_POWER_DISCONNECTED); - } - if (axp.isVbusPlugInIRQ()) { - DEBUG_MSG("USB plugged In\n"); - powerFSM.trigger(EVENT_POWER_CONNECTED); - } - if (axp.isBattPlugInIRQ()) { - DEBUG_MSG("Battery inserted\n"); - } - if (axp.isBattRemoveIRQ()) { - DEBUG_MSG("Battery removed\n"); - } - if (axp.isPEKShortPressIRQ()) { - DEBUG_MSG("PEK short button press\n"); - } - axp.clearIRQ(); + if (axp.isVbusRemoveIRQ()) { + DEBUG_MSG("USB unplugged\n"); + powerFSM.trigger(EVENT_POWER_DISCONNECTED); } + if (axp.isVbusPlugInIRQ()) { + DEBUG_MSG("USB plugged In\n"); + powerFSM.trigger(EVENT_POWER_CONNECTED); + } + /* + Other things we could check if we cared... + + if (axp.isChargingIRQ()) { + DEBUG_MSG("Battery start charging\n"); + } + if (axp.isChargingDoneIRQ()) { + DEBUG_MSG("Battery fully charged\n"); + } + if (axp.isBattPlugInIRQ()) { + DEBUG_MSG("Battery inserted\n"); + } + if (axp.isBattRemoveIRQ()) { + DEBUG_MSG("Battery removed\n"); + } + if (axp.isPEKShortPressIRQ()) { + DEBUG_MSG("PEK short button press\n"); + } + */ + axp.clearIRQ(); #endif // Only read once every 20 seconds once the power status for the app has been initialized diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index e6cc3738..6295b9dd 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -118,12 +118,21 @@ static void serialEnter() { setBluetoothEnable(false); screen->setOn(true); + screen->print("Using API...\n"); } static void powerEnter() { screen->setOn(true); setBluetoothEnable(true); + screen->print("Powered...\n"); +} + +static void powerExit() +{ + screen->setOn(true); + setBluetoothEnable(true); + screen->print("Unpowered...\n"); } static void onEnter() @@ -157,8 +166,7 @@ State stateDARK(darkEnter, NULL, NULL, "DARK"); State stateSERIAL(serialEnter, NULL, NULL, "SERIAL"); State stateBOOT(bootEnter, NULL, NULL, "BOOT"); State stateON(onEnter, NULL, NULL, "ON"); -State statePOWER(powerEnter, NULL, NULL, "POWER"); - +State statePOWER(powerEnter, NULL, powerExit, "POWER"); Fsm powerFSM(&stateBOOT); void PowerFSM_setup() diff --git a/src/PowerFSM.h b/src/PowerFSM.h index d996acbd..4af62040 100644 --- a/src/PowerFSM.h +++ b/src/PowerFSM.h @@ -20,6 +20,6 @@ #define EVENT_POWER_DISCONNECTED 14 extern Fsm powerFSM; -extern State statePOWER; +extern State statePOWER, stateSERIAL; void PowerFSM_setup(); diff --git a/src/concurrency/InterruptableDelay.cpp b/src/concurrency/InterruptableDelay.cpp index e7538235..80743cc2 100644 --- a/src/concurrency/InterruptableDelay.cpp +++ b/src/concurrency/InterruptableDelay.cpp @@ -4,30 +4,22 @@ namespace concurrency { -InterruptableDelay::InterruptableDelay() -{ -} +InterruptableDelay::InterruptableDelay() {} -InterruptableDelay::~InterruptableDelay() -{ -} +InterruptableDelay::~InterruptableDelay() {} /** * Returns false if we were interrupted */ bool InterruptableDelay::delay(uint32_t msec) { - if (msec) { - // DEBUG_MSG("delay %u ", msec); + // DEBUG_MSG("delay %u ", msec); - // sem take will return false if we timed out (i.e. were not interrupted) - bool r = semaphore.take(msec); + // sem take will return false if we timed out (i.e. were not interrupted) + bool r = semaphore.take(msec); - // DEBUG_MSG("interrupt=%d\n", r); - return !r; - } else { - return true; - } + // DEBUG_MSG("interrupt=%d\n", r); + return !r; } void InterruptableDelay::interrupt() diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index 96e18ac5..e4007aea 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -202,7 +202,7 @@ class Screen : public concurrency::OSThread return true; // claim success if our display is not in use else { bool success = cmdQueue.enqueue(cmd, 0); - setInterval(0); // handle ASAP + enabled = true; // handle ASAP (we are the registered reader for cmdQueue, but might have been disabled) return success; } } diff --git a/src/main.cpp b/src/main.cpp index 93c9558e..e258ec52 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -128,31 +128,13 @@ class PowerFSMThread : public OSThread /// If we are in power state we force the CPU to wake every 10ms to check for serial characters (we don't yet wake /// cpu for serial rx - FIXME) - canSleep = (powerFSM.getState() != &statePOWER); - + auto state = powerFSM.getState(); + canSleep = (state != &statePOWER) && (state != &stateSERIAL); + return 10; } }; -static Periodic *ledPeriodic; -static OSThread *powerFSMthread; - -// Prepare for button presses -#ifdef BUTTON_PIN -OneButton userButton; -#endif -#ifdef BUTTON_PIN_ALT -OneButton userButtonAlt; -#endif -void userButtonPressed() -{ - powerFSM.trigger(EVENT_PRESS); -} -void userButtonPressedLong() -{ - screen->adjustBrightness(); -} - /** * Watch a GPIO and if we get an IRQ, wake the main thread. * Use to add wake on button press @@ -168,6 +150,65 @@ void wakeOnIrq(int irq, int mode) FALLING); } +class ButtonThread : public OSThread +{ +// Prepare for button presses +#ifdef BUTTON_PIN + OneButton userButton; +#endif +#ifdef BUTTON_PIN_ALT + OneButton userButtonAlt; +#endif + + public: + // callback returns the period for the next callback invocation (or 0 if we should no longer be called) + ButtonThread() : OSThread("Button") + { +#ifdef BUTTON_PIN + userButton = OneButton(BUTTON_PIN, true, true); + userButton.attachClick(userButtonPressed); + userButton.attachDuringLongPress(userButtonPressedLong); + wakeOnIrq(BUTTON_PIN, FALLING); +#endif +#ifdef BUTTON_PIN_ALT + userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true); + userButtonAlt.attachClick(userButtonPressed); + userButton.attachDuringLongPress(userButtonPressedLong); + wakeOnIrq(BUTTON_PIN_ALT, FALLING); +#endif + } + + protected: + /// If the button is pressed we suppress CPU sleep until release + int32_t runOnce() + { + canSleep = true; // Assume we should not keep the board awake + +#ifdef BUTTON_PIN + userButton.tick(); + canSleep &= userButton.isIdle(); +#endif +#ifdef BUTTON_PIN_ALT + userButtonAlt.tick(); + canSleep &= userButton.isIdle(); +#endif + // if(!canSleep) DEBUG_MSG("Supressing sleep!\n"); + + return 5; + } + + private: + static void userButtonPressed() + { + // DEBUG_MSG("press!\n"); + powerFSM.trigger(EVENT_PRESS); + } + static void userButtonPressedLong() { screen->adjustBrightness(); } +}; + +static Periodic *ledPeriodic; +static OSThread *powerFSMthread, *buttonThread; + RadioInterface *rIf = NULL; void setup() @@ -210,18 +251,7 @@ void setup() #endif // Buttons & LED -#ifdef BUTTON_PIN - userButton = OneButton(BUTTON_PIN, true, true); - userButton.attachClick(userButtonPressed); - userButton.attachDuringLongPress(userButtonPressedLong); - wakeOnIrq(BUTTON_PIN, FALLING); -#endif -#ifdef BUTTON_PIN_ALT - userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true); - userButtonAlt.attachClick(userButtonPressed); - userButton.attachDuringLongPress(userButtonPressedLong); - wakeOnIrq(BUTTON_PIN_ALT, FALLING); -#endif + buttonThread = new ButtonThread(); #ifdef LED_PIN pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, 1 ^ LED_INVERTED); // turn on for now @@ -411,13 +441,6 @@ void loop() esp32Loop(); #endif -#ifdef BUTTON_PIN - userButton.tick(); -#endif -#ifdef BUTTON_PIN_ALT - userButtonAlt.tick(); -#endif - // For debugging // if (rIf) ((RadioLibInterface *)rIf)->isActivelyReceiving(); @@ -438,9 +461,9 @@ void loop() /* if (mainController.nextThread && delayMsec) DEBUG_MSG("Next %s in %ld\n", mainController.nextThread->ThreadName.c_str(), - mainController.nextThread->tillRun(millis())); - */ - + mainController.nextThread->tillRun(millis())); */ + // We want to sleep as long as possible here - because it saves power mainDelay.delay(delayMsec); + // if (didWake) DEBUG_MSG("wake!\n"); } From 02b1ece6ac8133334d53e28d3f4394bc1ea335a6 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sun, 11 Oct 2020 21:30:14 -0700 Subject: [PATCH 10/16] Update meshhttp.cpp --- src/meshwifi/meshhttp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index 49777913..b1553c7a 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -255,6 +255,7 @@ void middlewareLogging(HTTPRequest *req, HTTPResponse *res, std::function Date: Sun, 11 Oct 2020 22:13:14 -0700 Subject: [PATCH 11/16] Added a favicon.ico --- src/meshwifi/meshhttp.cpp | 17 ++++-- src/meshwifi/meshhttp.h | 122 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 130 insertions(+), 9 deletions(-) diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index b1553c7a..3cc6c374 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -49,6 +49,7 @@ void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res); void handleStyleCSS(HTTPRequest *req, HTTPResponse *res); void handleJSONChatHistoryDummy(HTTPRequest *req, HTTPResponse *res); void handleHotspot(HTTPRequest *req, HTTPResponse *res); +void handleFavicon(HTTPRequest *req, HTTPResponse *res); void handleRoot(HTTPRequest *req, HTTPResponse *res); void handle404(HTTPRequest *req, HTTPResponse *res); @@ -76,11 +77,10 @@ void handleWebResponse() // Slow down the CPU if we have not received a request within the last // 2 minutes. - if (millis () - timeSpeedUp >= (2 * 60 * 1000)) { + if (millis() - timeSpeedUp >= (2 * 60 * 1000)) { setCPUFast(false); // Set CPU to 80mhz timeSpeedUp = millis(); } - } void taskCreateCert(void *parameter) @@ -213,6 +213,7 @@ void initWebServer() ResourceNode *nodeCSS = new ResourceNode("/css/style.css", "GET", &handleStyleCSS); ResourceNode *nodeJS = new ResourceNode("/scripts/script.js", "GET", &handleJSONChatHistoryDummy); ResourceNode *nodeHotspot = new ResourceNode("/hotspot-detect.html", "GET", &handleHotspot); + ResourceNode *nodeFavicon = new ResourceNode("/favicon.ico", "GET", &handleFavicon); ResourceNode *nodeRoot = new ResourceNode("/", "GET", &handleRoot); ResourceNode *node404 = new ResourceNode("", "GET", &handle404); @@ -222,6 +223,7 @@ void initWebServer() secureServer->registerNode(nodeCSS); secureServer->registerNode(nodeJS); secureServer->registerNode(nodeHotspot); + secureServer->registerNode(nodeFavicon); secureServer->registerNode(nodeRoot); secureServer->setDefaultNode(node404); @@ -233,6 +235,7 @@ void initWebServer() insecureServer->registerNode(nodeCSS); insecureServer->registerNode(nodeJS); insecureServer->registerNode(nodeHotspot); + insecureServer->registerNode(nodeFavicon); insecureServer->registerNode(nodeRoot); insecureServer->setDefaultNode(node404); @@ -252,10 +255,8 @@ void middlewareLogging(HTTPRequest *req, HTTPResponse *res, std::functionprint(out); +} + +void handleFavicon(HTTPRequest *req, HTTPResponse *res) +{ + // Set Content-Type + res->setHeader("Content-Type", "image/vnd.microsoft.icon"); + // Write data from header file + res->write(FAVICON_DATA, FAVICON_LENGTH); } \ No newline at end of file diff --git a/src/meshwifi/meshhttp.h b/src/meshwifi/meshhttp.h index 42bb1d3b..38949b95 100644 --- a/src/meshwifi/meshhttp.h +++ b/src/meshwifi/meshhttp.h @@ -1,8 +1,8 @@ #pragma once +#include "PhoneAPI.h" #include #include -#include "PhoneAPI.h" void initWebServer(); void createSSLCert(); @@ -22,16 +22,128 @@ void handleRoot(); void handleScriptsScriptJS(); void handleJSONChatHistoryDummy(); +// Binary data for the favicon +const byte FAVICON_DATA[] = { + 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x20, 0x20, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0xA8, 0x08, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x84, + 0xDC, 0x3D, 0x00, 0x84, 0xDC, 0x3C, 0x00, 0x85, 0xDC, 0x3F, 0x00, 0x86, 0xDD, 0x40, 0x00, 0x83, 0xDC, 0x3C, 0x00, 0x85, 0xDC, + 0x3E, 0x00, 0x82, 0xDC, 0x3A, 0x00, 0x8B, 0xDE, 0x49, 0x00, 0x84, 0xDB, 0x3E, 0x00, 0x82, 0xD9, 0x3C, 0x00, 0x89, 0xDD, 0x45, + 0x00, 0x83, 0xDB, 0x3C, 0x00, 0x83, 0xD8, 0x3D, 0x00, 0x81, 0xD8, 0x3A, 0x00, 0x8D, 0xE0, 0x49, 0x00, 0x88, 0xE4, 0x3F, 0x00, + 0x89, 0xE9, 0x3E, 0x00, 0x84, 0xD8, 0x40, 0x00, 0x85, 0xDF, 0x3C, 0x00, 0x8E, 0xF2, 0x40, 0x00, 0x8D, 0xF6, 0x3D, 0x00, 0x90, + 0xEA, 0x49, 0x00, 0x82, 0xD5, 0x3E, 0x00, 0x78, 0xC1, 0x3A, 0x00, 0x90, 0xE9, 0x4A, 0x00, 0x8E, 0xF5, 0x3D, 0x00, 0x84, 0xDD, + 0x3D, 0x00, 0x91, 0xF7, 0x43, 0x00, 0x87, 0xE5, 0x3D, 0x00, 0x6C, 0xA2, 0x38, 0x00, 0x53, 0x65, 0x31, 0x00, 0x41, 0x39, 0x2E, + 0x00, 0x3A, 0x27, 0x2B, 0x00, 0x34, 0x1A, 0x2A, 0x00, 0x41, 0x38, 0x2E, 0x00, 0x82, 0xD8, 0x3D, 0x00, 0x88, 0xE7, 0x3D, 0x00, + 0x8E, 0xF3, 0x41, 0x00, 0x69, 0x95, 0x39, 0x00, 0x3E, 0x33, 0x2C, 0x00, 0x31, 0x11, 0x29, 0x00, 0x2E, 0x0A, 0x29, 0x00, 0x2D, + 0x0B, 0x27, 0x00, 0x30, 0x10, 0x29, 0x00, 0x34, 0x18, 0x2A, 0x00, 0x3E, 0x31, 0x2C, 0x00, 0x68, 0x95, 0x39, 0x00, 0x88, 0xE7, + 0x3E, 0x00, 0x82, 0xD7, 0x3C, 0x00, 0x84, 0xDD, 0x3C, 0x00, 0x8B, 0xEE, 0x3E, 0x00, 0x85, 0xDF, 0x3D, 0x00, 0x47, 0x48, 0x2E, + 0x00, 0x30, 0x0F, 0x29, 0x00, 0x31, 0x13, 0x29, 0x00, 0x48, 0x4D, 0x2E, 0x00, 0x61, 0x7F, 0x39, 0x00, 0x6A, 0x9C, 0x38, 0x00, + 0x75, 0xB8, 0x39, 0x00, 0x85, 0xDE, 0x3D, 0x00, 0x8C, 0xEF, 0x3E, 0x00, 0x89, 0xDE, 0x44, 0x00, 0x80, 0xD1, 0x3C, 0x00, 0x3A, + 0x28, 0x2C, 0x00, 0x32, 0x16, 0x2A, 0x00, 0x33, 0x17, 0x2A, 0x00, 0x4B, 0x50, 0x30, 0x00, 0x76, 0xBA, 0x3A, 0x00, 0x8A, 0xEF, + 0x3C, 0x00, 0x9A, 0xFE, 0x4D, 0x00, 0x95, 0xFF, 0x43, 0x00, 0x93, 0xFF, 0x40, 0x00, 0x4B, 0x52, 0x30, 0x00, 0x7E, 0xCE, 0x3C, + 0x00, 0x87, 0xD9, 0x44, 0x00, 0x34, 0x1B, 0x2A, 0x00, 0x65, 0x90, 0x36, 0x00, 0x8E, 0xF6, 0x3D, 0x00, 0x8F, 0xF7, 0x40, 0x00, + 0x8B, 0xDD, 0x48, 0x00, 0x73, 0xB1, 0x3A, 0x00, 0x66, 0x95, 0x35, 0x00, 0x66, 0x93, 0x35, 0x00, 0x35, 0x1B, 0x2A, 0x00, 0x8D, + 0xE8, 0x45, 0x00, 0x82, 0xD9, 0x3B, 0x00, 0x72, 0xAA, 0x3C, 0x00, 0x95, 0xFD, 0x46, 0x00, 0x8D, 0xF0, 0x40, 0x00, 0x57, 0x70, + 0x32, 0x00, 0x3C, 0x2D, 0x2C, 0x00, 0x2F, 0x0D, 0x29, 0x00, 0x81, 0xD4, 0x3D, 0x00, 0x8D, 0xF1, 0x40, 0x00, 0x94, 0xFC, 0x46, + 0x00, 0x73, 0xAE, 0x3D, 0x00, 0x45, 0x44, 0x2D, 0x00, 0x94, 0xF5, 0x49, 0x00, 0x90, 0xF0, 0x45, 0x00, 0x73, 0xAF, 0x3B, 0x00, + 0x38, 0x21, 0x2C, 0x00, 0x30, 0x11, 0x29, 0x00, 0x2F, 0x0F, 0x28, 0x00, 0x72, 0xAC, 0x3B, 0x00, 0x6A, 0x93, 0x3D, 0x00, 0x2E, + 0x0D, 0x27, 0x00, 0x35, 0x1C, 0x2B, 0x00, 0x36, 0x20, 0x2A, 0x00, 0x5E, 0x77, 0x39, 0x00, 0x78, 0xBE, 0x3B, 0x00, 0x36, 0x21, + 0x2A, 0x00, 0x71, 0xAB, 0x3B, 0x00, 0x4C, 0x54, 0x30, 0x00, 0x3D, 0x31, 0x2B, 0x00, 0x82, 0xD6, 0x3D, 0x00, 0x79, 0xC5, 0x39, + 0x00, 0x9A, 0xFF, 0x4D, 0x00, 0x8A, 0xE8, 0x40, 0x00, 0x8A, 0xE7, 0x40, 0x00, 0x7A, 0xC6, 0x39, 0x00, 0x3D, 0x2E, 0x2C, 0x00, + 0x81, 0xD5, 0x3D, 0x00, 0x77, 0xBC, 0x3A, 0x00, 0x31, 0x12, 0x2A, 0x00, 0x69, 0x9B, 0x37, 0x00, 0x8E, 0xF3, 0x40, 0x00, 0x83, + 0xDC, 0x3B, 0x00, 0x8C, 0xF6, 0x3B, 0x00, 0x88, 0xD9, 0x45, 0x00, 0x86, 0xE1, 0x3D, 0x00, 0x85, 0xE0, 0x3D, 0x00, 0x7B, 0xC8, + 0x39, 0x00, 0x36, 0x1F, 0x29, 0x00, 0x55, 0x6B, 0x32, 0x00, 0x8A, 0xEE, 0x3C, 0x00, 0x48, 0x4B, 0x2E, 0x00, 0x51, 0x61, 0x31, + 0x00, 0x8C, 0xE0, 0x48, 0x00, 0x8B, 0xDE, 0x47, 0x00, 0x98, 0xEE, 0x55, 0x00, 0x5D, 0x79, 0x36, 0x00, 0x3A, 0x2A, 0x2B, 0x00, + 0x3A, 0x29, 0x2B, 0x00, 0x5C, 0x78, 0x36, 0x00, 0x60, 0x7C, 0x3A, 0x00, 0x3D, 0x30, 0x2C, 0x00, 0x99, 0xFD, 0x4C, 0x00, 0x66, + 0x8A, 0x3C, 0x00, 0x2D, 0x0C, 0x27, 0x00, 0x42, 0x3C, 0x2E, 0x00, 0x84, 0xDA, 0x3E, 0x00, 0x88, 0xE5, 0x3F, 0x00, 0x37, 0x22, + 0x2B, 0x00, 0x2E, 0x0B, 0x28, 0x00, 0x6A, 0x9B, 0x37, 0x00, 0x72, 0xAF, 0x3A, 0x00, 0x32, 0x15, 0x29, 0x00, 0x2A, 0x00, 0x28, + 0x00, 0x5B, 0x75, 0x35, 0x00, 0x89, 0xE8, 0x3D, 0x00, 0x78, 0xBF, 0x3A, 0x00, 0x73, 0xB4, 0x38, 0x00, 0x83, 0xDA, 0x3C, 0x00, + 0x84, 0xDE, 0x3C, 0x00, 0x85, 0xDD, 0x3E, 0x00, 0x86, 0xDE, 0x40, 0x00, 0x84, 0xDE, 0x3B, 0x00, 0x86, 0xE2, 0x3C, 0x00, 0x85, + 0xDD, 0x3F, 0x00, 0x87, 0xE2, 0x3F, 0x00, 0x87, 0xE1, 0x3E, 0x00, 0x85, 0xDE, 0x3E, 0x00, 0x89, 0xE2, 0x41, 0x00, 0x89, 0xE2, + 0x43, 0x00, 0x84, 0xDC, 0x3E, 0x00, 0x83, 0xD8, 0x3E, 0x00, 0x90, 0xF6, 0x41, 0x00, 0x2B, 0x04, 0x28, 0x00, 0x8C, 0xE3, 0x47, + 0x00, 0x8B, 0xDE, 0x48, 0x00, 0x8A, 0xDC, 0x47, 0x00, 0x8A, 0xDD, 0x47, 0x00, 0x8D, 0xDD, 0x4A, 0x00, 0x8A, 0xDE, 0x47, 0x00, + 0x8B, 0xDD, 0x49, 0x00, 0x8B, 0xE0, 0x46, 0x00, 0x9A, 0xF2, 0x55, 0x00, 0x59, 0x70, 0x35, 0x00, 0x8F, 0xDE, 0x4F, 0x00, 0x82, + 0xDC, 0x3B, 0x00, 0x82, 0xDB, 0x39, 0x00, 0x7F, 0xD7, 0x38, 0x00, 0x92, 0xF0, 0x48, 0x00, 0x33, 0x19, 0x29, 0x00, 0x87, 0xDD, + 0x42, 0x00, 0x87, 0xDD, 0x41, 0x00, 0x92, 0xEC, 0x4B, 0x00, 0x78, 0xBD, 0x3C, 0x00, 0x86, 0xDD, 0x3F, 0x00, 0x81, 0xD9, 0x39, + 0x00, 0x7B, 0xC4, 0x3C, 0x00, 0x34, 0x1A, 0x29, 0x00, 0x89, 0xDD, 0x44, 0x00, 0x86, 0xDC, 0x40, 0x00, 0x88, 0xDD, 0x44, 0x00, + 0x87, 0xDE, 0x41, 0x00, 0x99, 0xFA, 0x4F, 0x00, 0x7B, 0xC3, 0x3E, 0x00, 0x83, 0xD7, 0x3F, 0x00, 0x8B, 0xED, 0x3E, 0x00, 0x40, + 0x33, 0x2F, 0x00, 0x39, 0x27, 0x2B, 0x00, 0x81, 0xD7, 0x3B, 0x00, 0x3B, 0x2C, 0x2A, 0x00, 0x33, 0x18, 0x29, 0x00, 0x38, 0x22, + 0x2B, 0x00, 0x85, 0xDA, 0x40, 0x00, 0x89, 0xEA, 0x3D, 0x00, 0x6F, 0xA9, 0x38, 0x00, 0x70, 0xAB, 0x38, 0x00, 0x85, 0xDD, 0x3D, + 0x00, 0x88, 0xE1, 0x40, 0x00, 0x36, 0x1F, 0x2B, 0x00, 0x30, 0x13, 0x28, 0x00, 0x68, 0x9A, 0x36, 0x00, 0x90, 0xFB, 0x3F, 0x00, + 0x8A, 0xDD, 0x46, 0x00, 0x8D, 0xE9, 0x45, 0x00, 0x5A, 0x71, 0x36, 0x00, 0x27, 0x00, 0x24, 0x00, 0x73, 0x9F, 0x45, 0x00, 0x97, + 0xFE, 0x4A, 0x00, 0x86, 0xD8, 0x43, 0x00, 0x73, 0xA1, 0x45, 0x00, 0x8E, 0xDF, 0x4C, 0x00, 0x85, 0xDB, 0x40, 0x00, 0x72, 0xB5, + 0x37, 0x00, 0x95, 0xF4, 0x4B, 0x00, 0x73, 0xB6, 0x37, 0x00, 0x88, 0xE9, 0x3C, 0x00, 0x8A, 0xDB, 0x48, 0x00, 0x8C, 0xDE, 0x49, + 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0xAE, 0x06, 0xF1, 0x02, 0x04, 0x04, 0x02, 0xF1, 0x06, 0xAE, 0x04, 0x03, 0x02, 0x01, 0x00, 0x01, + 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0xAE, 0xC7, 0xF1, 0x02, 0x04, + 0x04, 0x02, 0xF1, 0xC7, 0xAE, 0x04, 0x03, 0x02, 0x01, 0x00, 0x01, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x02, 0x03, 0x0B, 0xAE, 0xEF, 0xF0, 0x02, 0x01, 0x01, 0x02, 0xB4, 0xEF, 0xAE, 0x0B, 0x03, 0x02, 0x01, 0x00, + 0x01, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x05, 0xEB, 0xA7, 0xD1, 0xEC, 0xED, 0x96, + 0x04, 0x04, 0x96, 0xED, 0xEE, 0xD1, 0xA7, 0xEB, 0x05, 0x04, 0x01, 0x04, 0xCA, 0x04, 0x01, 0x01, 0x01, 0xCA, 0xCA, 0xCA, 0xCA, + 0xCA, 0xCA, 0xCA, 0xCC, 0xE2, 0x8A, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE8, 0xE7, 0xE9, 0xE5, 0xBB, 0xE3, 0x8A, 0xE2, 0xCC, + 0xCA, 0xCC, 0xEA, 0xCC, 0xCA, 0xCA, 0xCA, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x08, 0xDD, 0x55, 0xDE, 0x2C, 0xDF, + 0xE0, 0xE1, 0xE1, 0xE0, 0xDF, 0x2C, 0xDE, 0x55, 0xDD, 0x08, 0x04, 0x01, 0x04, 0xCA, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xC6, 0xD8, 0xD9, 0xAB, 0x78, 0x6A, 0x28, 0xDA, 0xDB, 0x28, 0x6A, 0x5A, 0xDC, 0xD9, 0xD8, 0xC6, + 0x01, 0x00, 0x01, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x05, 0x03, 0xD4, 0xD1, 0x31, + 0xD5, 0xD6, 0x98, 0xD7, 0xD6, 0xD5, 0x0B, 0x32, 0xD4, 0x03, 0x05, 0x04, 0x01, 0x04, 0xCA, 0x04, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x05, 0xC3, 0xC2, 0xA4, 0xD0, 0xD1, 0xB3, 0xD2, 0xD3, 0xD3, 0xD2, 0x4F, 0x32, 0xD0, 0xA4, 0xC2, + 0xC3, 0x05, 0x02, 0x05, 0xB7, 0x05, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xCB, 0xC2, 0xCC, 0x02, 0xCD, + 0x79, 0xCE, 0xCF, 0xC1, 0xC1, 0xCF, 0xCE, 0x79, 0xCD, 0x02, 0xCC, 0xC2, 0xCB, 0x03, 0xCB, 0xB3, 0xCB, 0x03, 0x03, 0x03, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x7E, 0x05, 0xC6, 0x7E, 0x00, 0xC7, 0x15, 0xC8, 0xC9, 0xC9, 0xC8, 0x15, 0xC7, 0x00, 0x7E, + 0xC6, 0x05, 0x7E, 0x04, 0x7E, 0xCA, 0x7E, 0x04, 0x04, 0x04, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0x00, 0x03, 0xC3, 0x00, + 0x05, 0x55, 0xC4, 0xC5, 0xC1, 0xC1, 0xC5, 0xC4, 0x55, 0x05, 0x00, 0xC3, 0x03, 0x00, 0xAE, 0x00, 0x3D, 0x00, 0xAE, 0xAE, 0xAE, + 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0x7E, 0xBE, 0x00, 0x05, 0xBE, 0x7E, 0xBF, 0xC0, 0x5C, 0xC1, 0xC1, 0x5C, 0xC0, 0xBF, 0x7E, + 0xBE, 0x05, 0x00, 0xBE, 0x7E, 0xBE, 0xC2, 0x06, 0xBD, 0xBD, 0xBD, 0xB3, 0xB3, 0xB3, 0xB4, 0xB5, 0xB3, 0xB3, 0xB5, 0xB6, 0xB6, + 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0x6B, 0x6B, 0xBB, 0xBA, 0xB9, 0xB8, 0xB7, 0xB6, 0xB6, 0xB5, 0xB3, 0xB5, 0xBC, 0xB4, 0xB3, 0xB3, + 0xB3, 0x02, 0x02, 0xA8, 0xA9, 0xAA, 0xA8, 0x02, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0x8F, 0xB1, 0x71, 0x2D, 0xB1, 0x9E, 0xB0, + 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0x02, 0xA4, 0xB2, 0xAA, 0xA8, 0x02, 0x02, 0x04, 0x31, 0xA3, 0x04, 0x31, 0x82, 0x3B, 0xA3, 0xA4, + 0xA5, 0xA6, 0x82, 0xA7, 0x8E, 0x20, 0x78, 0x78, 0x20, 0x8E, 0xA7, 0x82, 0xA6, 0xA5, 0xA4, 0xA3, 0x3B, 0x82, 0x3D, 0x04, 0xA3, + 0x31, 0x04, 0x09, 0x9F, 0xA0, 0x21, 0x2C, 0xA1, 0x47, 0x52, 0x5B, 0x5A, 0xA2, 0x1C, 0x81, 0x8D, 0x8E, 0x91, 0x91, 0x8E, 0x8D, + 0x81, 0x1C, 0xA2, 0x5A, 0x5B, 0x52, 0x47, 0xA1, 0x2C, 0x21, 0xA0, 0x9F, 0x09, 0x96, 0x97, 0x16, 0x98, 0x99, 0x9A, 0x46, 0x9B, + 0x28, 0x9C, 0x6D, 0x76, 0x7D, 0x8C, 0x9D, 0x8E, 0x8E, 0x9D, 0x9E, 0x7D, 0x75, 0x6D, 0x9C, 0x65, 0x9B, 0x46, 0x39, 0x99, 0x98, + 0x16, 0x97, 0x96, 0x4F, 0x89, 0x15, 0x1F, 0x69, 0x38, 0x45, 0x8A, 0x78, 0x66, 0x6C, 0x74, 0x4A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x8B, 0x80, 0x45, 0x90, 0x66, 0x91, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x15, 0x89, 0x4F, 0x7E, 0x0D, 0x14, 0x1E, 0x29, 0x37, 0x44, + 0x14, 0x59, 0x65, 0x6B, 0x73, 0x7F, 0x80, 0x25, 0x81, 0x82, 0x25, 0x80, 0x7F, 0x83, 0x84, 0x65, 0x85, 0x4D, 0x86, 0x87, 0x29, + 0x88, 0x14, 0x0D, 0x7E, 0x05, 0x0C, 0x13, 0x1D, 0x28, 0x2C, 0x43, 0x4E, 0x72, 0x64, 0x53, 0x5A, 0x73, 0x74, 0x75, 0x1C, 0x1C, + 0x76, 0x74, 0x77, 0x78, 0x6A, 0x64, 0x79, 0x4E, 0x7A, 0x2C, 0x7B, 0x7C, 0x7D, 0x0C, 0x05, 0x04, 0x0B, 0x12, 0x1C, 0x27, 0x36, + 0x42, 0x4D, 0x5D, 0x63, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x1A, 0x1A, 0x6D, 0x6C, 0x6E, 0x53, 0x69, 0x6F, 0x5D, 0x19, 0x70, 0x36, + 0x71, 0x24, 0x12, 0x0B, 0x04, 0x03, 0x03, 0x11, 0x1B, 0x2E, 0x35, 0x41, 0x4C, 0x5E, 0x62, 0x63, 0x64, 0x65, 0x66, 0x2C, 0x5A, + 0x5A, 0x2C, 0x66, 0x65, 0x64, 0x67, 0x62, 0x5E, 0x52, 0x40, 0x65, 0x68, 0x1B, 0x11, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x25, + 0x34, 0x40, 0x4B, 0x56, 0x57, 0x58, 0x16, 0x59, 0x5A, 0x41, 0x5B, 0x5B, 0x41, 0x5A, 0x59, 0x5C, 0x5D, 0x5E, 0x5F, 0x21, 0x41, + 0x60, 0x61, 0x05, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x09, 0x24, 0x33, 0x3F, 0x2C, 0x4B, 0x4C, 0x4D, 0x4E, 0x14, 0x4F, 0x50, + 0x51, 0x51, 0x50, 0x4F, 0x14, 0x4E, 0x4D, 0x52, 0x53, 0x2C, 0x3F, 0x01, 0x54, 0x55, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1A, + 0x23, 0x32, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x47, 0x46, 0x45, 0x44, 0x43, 0x48, 0x41, 0x40, 0x3F, + 0x49, 0x3C, 0x4A, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x30, 0x32, 0x33, 0x34, 0x35, 0x36, 0x2C, 0x37, 0x38, + 0x39, 0x3A, 0x3A, 0x39, 0x38, 0x37, 0x2C, 0x36, 0x35, 0x34, 0x3B, 0x3C, 0x30, 0x3D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1A, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2C, 0x2B, 0x2A, 0x29, 0x28, 0x2D, 0x2E, 0x13, + 0x2F, 0x30, 0x31, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x09, 0x02, 0x1B, 0x1C, 0x1D, 0x1E, + 0x1F, 0x20, 0x21, 0x21, 0x20, 0x22, 0x1E, 0x1D, 0x1C, 0x1B, 0x02, 0x09, 0x1A, 0x01, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x17, 0x16, 0x18, 0x19, 0x13, 0x12, 0x11, + 0x02, 0x01, 0x00, 0x01, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x0B, 0x0C, + 0x0D, 0x0E, 0x0F, 0x10, 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x03, 0x02, 0x01, 0x00, 0x01, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x00, 0x01, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +// Length of the binary data +const int FAVICON_LENGTH = 2238; + class httpAPI : public PhoneAPI { -public: + public: // Nothing here yet -private: + private: // Nothing here yet -protected: + protected: // Nothing here yet - }; \ No newline at end of file From 97adb598b6897e19858f799ff09ff5be0e05b812 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Wed, 14 Oct 2020 16:17:12 -0700 Subject: [PATCH 12/16] toRadio is functional --- src/meshwifi/meshhttp.cpp | 49 ++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index 3cc6c374..294d788c 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -78,7 +78,7 @@ void handleWebResponse() // Slow down the CPU if we have not received a request within the last // 2 minutes. if (millis() - timeSpeedUp >= (2 * 60 * 1000)) { - setCPUFast(false); // Set CPU to 80mhz + setCpuFrequencyMhz(80); timeSpeedUp = millis(); } } @@ -105,7 +105,7 @@ void taskCreateCert(void *parameter) DEBUG_MSG("Existing SSL Certificate found!\n"); } else { DEBUG_MSG("Creating the certificate. This may take a while. Please wait...\n"); - +screen->print("Powered...\n"); cert = new SSLCert(); // disableCore1WDT(); int createCertResult = createSelfSignedCert(*cert, KEYSIZE_2048, "CN=meshtastic.local,O=Meshtastic,C=US", @@ -208,7 +208,7 @@ void initWebServer() // For every resource available on the server, we need to create a ResourceNode // The ResourceNode links URL and HTTP method to a handler function - ResourceNode *nodeAPIv1ToRadio = new ResourceNode("/api/v1/toradio", "GET", &handleAPIv1ToRadio); + ResourceNode *nodeAPIv1ToRadio = new ResourceNode("/api/v1/toradio", "PUT", &handleAPIv1ToRadio); ResourceNode *nodeAPIv1FromRadio = new ResourceNode("/api/v1/fromradio", "GET", &handleAPIv1FromRadio); ResourceNode *nodeCSS = new ResourceNode("/css/style.css", "GET", &handleStyleCSS); ResourceNode *nodeJS = new ResourceNode("/scripts/script.js", "GET", &handleJSONChatHistoryDummy); @@ -253,7 +253,8 @@ void middlewareLogging(HTTPRequest *req, HTTPResponse *res, std::functionsetHeader("Content-Type", "application/x-protobuf"); + //res->setHeader("Content-Type", "application/json"); uint8_t txBuf[MAX_STREAM_BUF_SIZE]; @@ -324,15 +330,36 @@ void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res) void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res) { - DEBUG_MSG("webAPI handleAPIv1ToRadio\n"); + DEBUG_MSG("+++++++++++++++ webAPI handleAPIv1ToRadio\n"); + + /* + For documentation, see: + https://github.com/meshtastic/Meshtastic-device/wiki/HTTP-REST-API-discussion + https://github.com/meshtastic/Meshtastic-device/blob/master/docs/software/device-api.md + + Example: + http://10.10.30.198/api/v1/toradio + */ // Status code is 200 OK by default. - // We want to deliver a simple HTML page, so we send a corresponding content type: res->setHeader("Content-Type", "application/x-protobuf"); + //res->setHeader("Content-Type", "application/json"); - // The response implements the Print interface, so you can use it just like - // you would write to Serial etc. - res->print(""); + // webAPI.handleToRadio(p); + + // We use text/plain for the response + //res->setHeader("Content-Type", "text/plain"); + + // Stream the incoming request body to the response body + // Theoretically, this should work for every request size. + byte buffer[MAX_TO_FROM_RADIO_SIZE]; + size_t s = req->readBytes(buffer, MAX_TO_FROM_RADIO_SIZE); + + DEBUG_MSG("Received %d bytes from PUT request\n", s); + webAPI.handleToRadio(buffer, s); + + res->write(buffer, s); + DEBUG_MSG("--------------- webAPI handleAPIv1ToRadio\n"); } /* From 3b2f5fa5e36d83c9f7e57908b2c19db694395b41 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Wed, 14 Oct 2020 20:24:19 -0700 Subject: [PATCH 13/16] fromRadio now returns all the vailable protobufs. a request to http sets the cpu clock to 160mhz, https to 240mhz then will clock it back down after 2 minutes. --- src/meshwifi/meshhttp.cpp | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index 294d788c..625b07fe 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -31,8 +31,6 @@ Preferences prefs; #include #include -#define HEADER_LEN 4 - // The HTTPS Server comes in a separate namespace. For easier use, include it here. using namespace httpsserver; @@ -53,7 +51,8 @@ void handleFavicon(HTTPRequest *req, HTTPResponse *res); void handleRoot(HTTPRequest *req, HTTPResponse *res); void handle404(HTTPRequest *req, HTTPResponse *res); -void middlewareLogging(HTTPRequest *req, HTTPResponse *res, std::function next); +void middlewareSpeedUp240(HTTPRequest *req, HTTPResponse *res, std::function next); +void middlewareSpeedUp160(HTTPRequest *req, HTTPResponse *res, std::function next); bool isWebServerReady = 0; bool isCertReady = 0; @@ -227,7 +226,7 @@ void initWebServer() secureServer->registerNode(nodeRoot); secureServer->setDefaultNode(node404); - secureServer->addMiddleware(&middlewareLogging); + secureServer->addMiddleware(&middlewareSpeedUp240); // Insecure nodes insecureServer->registerNode(nodeAPIv1ToRadio); @@ -239,6 +238,9 @@ void initWebServer() insecureServer->registerNode(nodeRoot); insecureServer->setDefaultNode(node404); + insecureServer->addMiddleware(&middlewareSpeedUp160); + + DEBUG_MSG("Starting Web Server...\n"); secureServer->start(); insecureServer->start(); @@ -248,16 +250,24 @@ void initWebServer() } } -void middlewareLogging(HTTPRequest *req, HTTPResponse *res, std::function next) +void middlewareSpeedUp240(HTTPRequest *req, HTTPResponse *res, std::function next) { // We want to print the response status, so we need to call next() first. next(); - //setCPUFast(true); // Set CPU to 240mhz when we're plugged in to wall power. setCpuFrequencyMhz(240); timeSpeedUp = millis(); } +void middlewareSpeedUp160(HTTPRequest *req, HTTPResponse *res, std::function next) +{ + // We want to print the response status, so we need to call next() first. + next(); + + setCpuFrequencyMhz(160); + timeSpeedUp = millis(); +} + void handle404(HTTPRequest *req, HTTPResponse *res) { @@ -322,9 +332,13 @@ void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res) uint8_t txBuf[MAX_STREAM_BUF_SIZE]; - uint32_t len = webAPI.getFromRadio(txBuf + HEADER_LEN); + + uint32_t len = 1; + while (len) { + len = webAPI.getFromRadio(txBuf); + res->write(txBuf, len); + } - res->write(txBuf, len); DEBUG_MSG("--------------- webAPI handleAPIv1FromRadio, len %d\n", len); } From 038ddb887ff794cfec4415ebbea13418394df867 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Thu, 15 Oct 2020 19:28:20 -0700 Subject: [PATCH 14/16] Be a little smarter with setting the CPU frequency in the event we have HTTPS and HTTP requests within close periods, let the speed set by the HTTPS request take presidence. --- src/meshwifi/meshhttp.cpp | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index 625b07fe..38492db3 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -53,6 +53,7 @@ void handle404(HTTPRequest *req, HTTPResponse *res); void middlewareSpeedUp240(HTTPRequest *req, HTTPResponse *res, std::function next); void middlewareSpeedUp160(HTTPRequest *req, HTTPResponse *res, std::function next); +void middlewareSession(HTTPRequest *req, HTTPResponse *res, std::function next); bool isWebServerReady = 0; bool isCertReady = 0; @@ -104,7 +105,6 @@ void taskCreateCert(void *parameter) DEBUG_MSG("Existing SSL Certificate found!\n"); } else { DEBUG_MSG("Creating the certificate. This may take a while. Please wait...\n"); -screen->print("Powered...\n"); cert = new SSLCert(); // disableCore1WDT(); int createCertResult = createSelfSignedCert(*cert, KEYSIZE_2048, "CN=meshtastic.local,O=Meshtastic,C=US", @@ -240,7 +240,6 @@ void initWebServer() insecureServer->addMiddleware(&middlewareSpeedUp160); - DEBUG_MSG("Starting Web Server...\n"); secureServer->start(); insecureServer->start(); @@ -264,7 +263,12 @@ void middlewareSpeedUp160(HTTPRequest *req, HTTPResponse *res, std::functionsetHeader("Content-Type", "application/x-protobuf"); - //res->setHeader("Content-Type", "application/json"); uint8_t txBuf[MAX_STREAM_BUF_SIZE]; - uint32_t len = 1; while (len) { len = webAPI.getFromRadio(txBuf); @@ -357,15 +359,7 @@ void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res) // Status code is 200 OK by default. res->setHeader("Content-Type", "application/x-protobuf"); - //res->setHeader("Content-Type", "application/json"); - // webAPI.handleToRadio(p); - - // We use text/plain for the response - //res->setHeader("Content-Type", "text/plain"); - - // Stream the incoming request body to the response body - // Theoretically, this should work for every request size. byte buffer[MAX_TO_FROM_RADIO_SIZE]; size_t s = req->readBytes(buffer, MAX_TO_FROM_RADIO_SIZE); From 05ca3c3d562c8856378fdd58e2a1243cc90edf24 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 17 Oct 2020 08:44:04 +0800 Subject: [PATCH 15/16] Update to work with my font size change --- src/graphics/Screen.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index b361505d..a97e04b9 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1100,8 +1100,9 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat #ifndef NO_ESP32 // Show CPU Frequency. - display->drawString(x + SCREEN_WIDTH - display->getStringWidth("CPU " + String(getCpuFrequencyMhz()) + "MHz"), y + FONT_HEIGHT * 1, - "CPU " + String(getCpuFrequencyMhz()) + "MHz"); + display->drawString(x + SCREEN_WIDTH - display->getStringWidth("CPU " + String(getCpuFrequencyMhz()) + "MHz"), + y + FONT_HEIGHT_SMALL * 1, + "CPU " + String(getCpuFrequencyMhz()) + "MHz"); #endif // Line 3 From 59ec87f5b0ae21d6f0bde3d4546322f415cfedde Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 17 Oct 2020 09:58:34 +0800 Subject: [PATCH 16/16] oops tbeam was inheriting from arduino, it should inherit from esp32 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 3b7c6abb..507f1a69 100644 --- a/platformio.ini +++ b/platformio.ini @@ -120,7 +120,7 @@ board_build.partitions = partition-table.csv extends = esp32_base board = ttgo-t-beam lib_deps = - ${arduino_base.lib_deps} + ${esp32_base.lib_deps} build_flags = ${esp32_base.build_flags} -D TBEAM_V10