diff --git a/platformio.ini b/platformio.ini index 015aa105b..327c5d6ca 100644 --- a/platformio.ini +++ b/platformio.ini @@ -103,7 +103,7 @@ lib_deps = # board_build.ldscript = linker/esp32.extram.bss.ld lib_ignore = segger_rtt platform_packages = - framework-arduinoespressif32@https://github.com/meshtastic/arduino-esp32.git#2814f110aa618429bdd9a0a2d6a93c55f29f87a6 + framework-arduinoespressif32@https://github.com/meshtastic/arduino-esp32.git#c29e0bcde1b1b4a939dd7339dea0302d2d589ae7 ; customize the partition table ; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index a6ee29c98..85e08f536 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -144,12 +144,12 @@ static void onEnter() uint32_t now = millis(); - if (now - lastPingMs > 30 * 1000) { // if more than a minute since our last press, ask node we are looking at to update their state + if (now - lastPingMs > + 30 * 1000) { // if more than a minute since our last press, ask node we are looking at to update their state if (displayedNodeNum) service.sendNetworkPing(displayedNodeNum, true); // Refresh the currently displayed node lastPingMs = now; } - } static void screenPress() @@ -171,11 +171,17 @@ Fsm powerFSM(&stateBOOT); void PowerFSM_setup() { + bool isRouter = radioConfig.preferences.is_router; + // If we are not a router and we already have AC power go to POWER state after init, otherwise go to ON // We assume routers might be powered all the time, but from a low current (solar) source - bool isRouter = radioConfig.preferences.is_router; bool isLowPower = radioConfig.preferences.is_low_power || isRouter; - bool hasPower = !isLowPower && powerStatus && powerStatus->getHasUSB(); + + /* To determine if we're externally powered, assumptions + 1) If we're powered up and there's no battery, we must be getting power externally. + 2) If we detect USB power from the power management chip, we must be getting power externally. + */ + bool hasPower = (powerStatus && !powerStatus->getHasBattery()) || (!isLowPower && powerStatus && powerStatus->getHasUSB()); DEBUG_MSG("PowerFSM init, USB power=%d\n", hasPower); powerFSM.add_timed_transition(&stateBOOT, hasPower ? &statePOWER : &stateON, 3 * 1000, NULL, "boot timeout"); diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 229aa63a1..3f98969d1 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -894,6 +894,22 @@ void Screen::handleStartBluetoothPinScreen(uint32_t pin) setFastFramerate(); } +void Screen::blink() { + setFastFramerate(); + uint8_t count = 10; + dispdev.setBrightness(254); + while(count>0) { + dispdev.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + dispdev.display(); + delay(50); + dispdev.clear(); + dispdev.display(); + delay(50); + count = count -1; + } + dispdev.setBrightness(brightness); +} + void Screen::handlePrint(const char *text) { DEBUG_MSG("Screen: %s", text); diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index 90e8ad089..888f31011 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -107,6 +107,8 @@ class Screen : public concurrency::OSThread */ void doDeepSleep(); + void blink(); + /// Handles a button press. void onPress() { enqueueCmd(ScreenCmd{.cmd = Cmd::ON_PRESS}); } diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index b1cefb706..a0183f340 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -60,6 +60,9 @@ void handleRestart(HTTPRequest *req, HTTPResponse *res); void handle404(HTTPRequest *req, HTTPResponse *res); void handleFormUpload(HTTPRequest *req, HTTPResponse *res); void handleScanNetworks(HTTPRequest *req, HTTPResponse *res); +void handleSpiffsBrowseStatic(HTTPRequest *req, HTTPResponse *res); +void handleSpiffsDeleteStatic(HTTPRequest *req, HTTPResponse *res); +void handleBlinkLED(HTTPRequest *req, HTTPResponse *res); void middlewareSpeedUp240(HTTPRequest *req, HTTPResponse *res, std::function next); void middlewareSpeedUp160(HTTPRequest *req, HTTPResponse *res, std::function next); @@ -76,7 +79,8 @@ char contentTypes[][2][32] = {{".txt", "text/plain"}, {".html", "text/html"} {".js", "text/javascript"}, {".png", "image/png"}, {".jpg", "image/jpg"}, {".gz", "application/gzip"}, {".gif", "image/gif"}, {".json", "application/json"}, - {".css", "text/css"}, {"", ""}}; + {".css", "text/css"}, {".ico","image/vnd.microsoft.icon"}, + {".svg", "image/svg+xml"}, {"", ""}}; void handleWebResponse() { @@ -125,11 +129,12 @@ 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"); + yield(); cert = new SSLCert(); - // disableCore1WDT(); + yield(); int createCertResult = createSelfSignedCert(*cert, KEYSIZE_2048, "CN=meshtastic.local,O=Meshtastic,C=US", "20190101000000", "20300101000000"); - // enableCore1WDT(); + yield(); if (createCertResult != 0) { DEBUG_MSG("Creating the certificate failed\n"); @@ -241,6 +246,9 @@ void initWebServer() ResourceNode *node404 = new ResourceNode("", "GET", &handle404); ResourceNode *nodeFormUpload = new ResourceNode("/upload", "POST", &handleFormUpload); ResourceNode *nodeJsonScanNetworks = new ResourceNode("/json/scanNetworks", "GET", &handleScanNetworks); + ResourceNode *nodeJsonBlinkLED = new ResourceNode("/json/blink", "POST", &handleBlinkLED); + ResourceNode *nodeJsonSpiffsBrowseStatic = new ResourceNode("/json/spiffs/browse/static/", "GET", &handleSpiffsBrowseStatic); + ResourceNode *nodeJsonDelete = new ResourceNode("/json/spiffs/delete/static", "DELETE", &handleSpiffsDeleteStatic); // Secure nodes secureServer->registerNode(nodeAPIv1ToRadioOptions); @@ -255,6 +263,9 @@ void initWebServer() secureServer->registerNode(nodeRestart); secureServer->registerNode(nodeFormUpload); secureServer->registerNode(nodeJsonScanNetworks); + secureServer->registerNode(nodeJsonBlinkLED); + secureServer->registerNode(nodeJsonSpiffsBrowseStatic); + secureServer->registerNode(nodeJsonDelete); secureServer->setDefaultNode(node404); secureServer->addMiddleware(&middlewareSpeedUp240); @@ -272,6 +283,9 @@ void initWebServer() insecureServer->registerNode(nodeRestart); insecureServer->registerNode(nodeFormUpload); insecureServer->registerNode(nodeJsonScanNetworks); + insecureServer->registerNode(nodeJsonBlinkLED); + insecureServer->registerNode(nodeJsonSpiffsBrowseStatic); + insecureServer->registerNode(nodeJsonDelete); insecureServer->setDefaultNode(node404); insecureServer->addMiddleware(&middlewareSpeedUp160); @@ -379,6 +393,84 @@ void handleStaticPost(HTTPRequest *req, HTTPResponse *res) res->println(""); } +void handleSpiffsBrowseStatic(HTTPRequest *req, HTTPResponse *res) +{ + // jm + + res->setHeader("Content-Type", "application/json"); + // res->setHeader("Content-Type", "text/html"); + + File root = SPIFFS.open("/"); + + if (root.isDirectory()) { + res->println("{"); + res->println("\"data\": {"); + + File file = root.openNextFile(); + res->print("\"files\": ["); + bool firstFile = 1; + while (file) { + String filePath = String(file.name()); + if (filePath.indexOf("/static") == 0) { + if (firstFile) { + firstFile = 0; + } else { + res->println(","); + } + + res->println("{"); + + if (String(file.name()).substring(1).endsWith(".gz")) { + String modifiedFile = String(file.name()).substring(1); + modifiedFile.remove((modifiedFile.length() - 3), 3); + res->print("\"nameModified\": \"" + modifiedFile + "\","); + res->print("\"name\": \"" + String(file.name()).substring(1) + "\","); + + } else { + res->print("\"name\": \"" + String(file.name()).substring(1) + "\","); + } + res->print("\"size\": " + String(file.size())); + res->print("}"); + } + + file = root.openNextFile(); + } + res->print("],"); + res->print("\"filesystem\" : {"); + res->print("\"total\" : " + String(SPIFFS.totalBytes()) + ","); + res->print("\"used\" : " + String(SPIFFS.usedBytes()) + ","); + res->print("\"free\" : " + String(SPIFFS.totalBytes() - SPIFFS.usedBytes())); + res->println("}"); + res->println("},"); + res->println("\"status\": \"ok\""); + res->println("}"); + } +} + +void handleSpiffsDeleteStatic(HTTPRequest *req, HTTPResponse *res) +{ + ResourceParameters *params = req->getParams(); + std::string paramValDelete; + + res->setHeader("Content-Type", "application/json"); + if (params->getQueryParameter("delete", paramValDelete)) { + std::string pathDelete = "/" + paramValDelete; + if (SPIFFS.remove(pathDelete.c_str())) { + Serial.println(pathDelete.c_str()); + res->println("{"); + res->println("\"status\": \"ok\""); + res->println("}"); + return; + } else { + Serial.println(pathDelete.c_str()); + res->println("{"); + res->println("\"status\": \"Error\""); + res->println("}"); + return; + } + } +} + void handleStaticBrowse(HTTPRequest *req, HTTPResponse *res) { // Get access to the parameters @@ -911,6 +1003,37 @@ void handleRestart(HTTPRequest *req, HTTPResponse *res) ESP.restart(); } +void handleBlinkLED(HTTPRequest *req, HTTPResponse *res) +{ + res->setHeader("Content-Type", "application/json"); + + ResourceParameters *params = req->getParams(); + std::string blink_target; + + if (!params->getQueryParameter("blink_target", blink_target)) { + // if no blink_target was supplied in the URL parameters of the + // POST request, then assume we should blink the LED + blink_target = "LED"; + } + + if (blink_target == "LED") { + uint8_t count = 10; + while (count > 0) { + setLed(true); + delay(50); + setLed(false); + delay(50); + count = count - 1; + } + } else { + screen->blink(); + } + + res->println("{"); + res->println("\"status\": \"ok\""); + res->println("}"); +} + void handleScanNetworks(HTTPRequest *req, HTTPResponse *res) { res->setHeader("Content-Type", "application/json"); @@ -929,17 +1052,16 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res) for (int i = 0; i < n; ++i) { char ssidArray[50]; String ssidString = String(WiFi.SSID(i)); - //String ssidString = String(WiFi.SSID(i)).toCharArray(ssidArray, WiFi.SSID(i).length()); + // String ssidString = String(WiFi.SSID(i)).toCharArray(ssidArray, WiFi.SSID(i).length()); ssidString.replace("\"", "\\\""); ssidString.toCharArray(ssidArray, 50); - - + if (WiFi.encryptionType(i) != WIFI_AUTH_OPEN) { - //res->println("{\"ssid\": \"%s\",\"rssi\": -75}, ", String(WiFi.SSID(i).c_str() ); - - res->printf("{\"ssid\": \"%s\",\"rssi\": %d}", ssidArray, WiFi.RSSI(i) ) ; - //WiFi.RSSI(i) - if (i != n-1) { + // res->println("{\"ssid\": \"%s\",\"rssi\": -75}, ", String(WiFi.SSID(i).c_str() ); + + res->printf("{\"ssid\": \"%s\",\"rssi\": %d}", ssidArray, WiFi.RSSI(i)); + // WiFi.RSSI(i) + if (i != n - 1) { res->printf(","); } } @@ -953,7 +1075,6 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res) res->println("},"); res->println("\"status\": \"ok\""); res->println("}"); - } void handleFavicon(HTTPRequest *req, HTTPResponse *res) diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index 16ae61850..54358077a 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -40,12 +40,14 @@ bool isWifiAvailable() const char *wifiName = radioConfig.preferences.wifi_ssid; const char *wifiPsw = radioConfig.preferences.wifi_password; - // strcpy(radioConfig.preferences.wifi_ssid, ""); - // strcpy(radioConfig.preferences.wifi_password, ""); + // strcpy(radioConfig.preferences.wifi_ssid, "meshtastic"); + // strcpy(radioConfig.preferences.wifi_password, "meshtastic!"); // strcpy(radioConfig.preferences.wifi_ssid, "meshtasticAdmin"); // strcpy(radioConfig.preferences.wifi_password, "12345678"); + // radioConfig.preferences.wifi_ap_mode = true; + // radioConfig.preferences.wifi_ap_mode = false; if (*wifiName && *wifiPsw) { return 1; @@ -221,9 +223,16 @@ static void WiFiEvent(WiFiEvent_t event) DEBUG_MSG("Obtained IP address: \n"); Serial.println(WiFi.localIP()); - // Start web server - initWebServer(); - initApiServer(); + if (!APStartupComplete) { + // Start web server + DEBUG_MSG("... Starting network services\n"); + initWebServer(); + initApiServer(); + + APStartupComplete = true; + } else { + DEBUG_MSG("... Not starting network services (They're already running)\n"); + } break; case SYSTEM_EVENT_STA_LOST_IP: @@ -253,7 +262,7 @@ static void WiFiEvent(WiFiEvent_t event) APStartupComplete = true; } else { - DEBUG_MSG("... Not starting network services\n"); + DEBUG_MSG("... Not starting network services (They're already running)\n"); } break;