Merge pull request #559 from mc-hamster/master

Endpoint to restart device, new sequence to force device into softAP, network scanner
This commit is contained in:
Jm Casler 2020-12-12 22:43:37 -08:00 committed by GitHub
commit 651d045afe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 180 additions and 39 deletions

View File

@ -984,7 +984,9 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
// The coordinates define the left starting point of the text // The coordinates define the left starting point of the text
display->setTextAlignment(TEXT_ALIGN_LEFT); display->setTextAlignment(TEXT_ALIGN_LEFT);
if (radioConfig.preferences.wifi_ap_mode) { if (isSoftAPForced()) {
display->drawString(x, y, String("WiFi: Software AP (Admin)"));
} else if (radioConfig.preferences.wifi_ap_mode) {
display->drawString(x, y, String("WiFi: Software AP")); display->drawString(x, y, String("WiFi: Software AP"));
} else if (WiFi.status() != WL_CONNECTED) { } else if (WiFi.status() != WL_CONNECTED) {
display->drawString(x, y, String("WiFi: Not Connected")); display->drawString(x, y, String("WiFi: Not Connected"));
@ -1007,13 +1009,15 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
- WL_NO_SHIELD: assigned when no WiFi shield is present; - WL_NO_SHIELD: assigned when no WiFi shield is present;
*/ */
if (WiFi.status() == WL_CONNECTED || isSoftAPForced() || radioConfig.preferences.wifi_ap_mode) {
if (WiFi.status() == WL_CONNECTED) { if (radioConfig.preferences.wifi_ap_mode || isSoftAPForced()) {
if (radioConfig.preferences.wifi_ap_mode) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.softAPIP().toString().c_str())); display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.softAPIP().toString().c_str()));
} else { } else {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.localIP().toString().c_str())); display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.localIP().toString().c_str()));
} }
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("(" + String(WiFi.softAPgetStationNum()) + "/4)"),
y + FONT_HEIGHT_SMALL * 1, "(" + String(WiFi.softAPgetStationNum()) + "/4)");
} else if (WiFi.status() == WL_NO_SSID_AVAIL) { } else if (WiFi.status() == WL_NO_SSID_AVAIL) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "SSID Not Found"); display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "SSID Not Found");
} else if (WiFi.status() == WL_CONNECTION_LOST) { } else if (WiFi.status() == WL_CONNECTION_LOST) {
@ -1088,10 +1092,19 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
} }
} }
if ((millis() / 10000) % 2) { if (isSoftAPForced()) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName)); if ((millis() / 10000) % 2) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: meshtasticAdmin");
} else {
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "PWD: 12345678");
}
} else { } else {
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "PWD: " + String(wifiPsw)); if ((millis() / 10000) % 2) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName));
} else {
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "PWD: " + String(wifiPsw));
}
} }
display->drawString(x, y + FONT_HEIGHT_SMALL * 3, "http://meshtastic.local"); display->drawString(x, y + FONT_HEIGHT_SMALL * 3, "http://meshtastic.local");
@ -1185,8 +1198,7 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg)
// DEBUG_MSG("Screen got status update %d\n", arg->getStatusType()); // DEBUG_MSG("Screen got status update %d\n", arg->getStatusType());
switch (arg->getStatusType()) { switch (arg->getStatusType()) {
case STATUS_TYPE_NODE: case STATUS_TYPE_NODE:
if (showingNormalScreen && if (showingNormalScreen && nodeStatus->getLastNumTotal() != nodeStatus->getNumTotal()) {
nodeStatus->getLastNumTotal() != nodeStatus->getNumTotal()) {
setFrames(); // Regen the list of screens setFrames(); // Regen the list of screens
} }
nodeDB.updateGUI = false; nodeDB.updateGUI = false;

View File

@ -241,7 +241,7 @@ class ButtonThread : public OSThread
} }
#endif #endif
} else { } else {
//DEBUG_MSG("Long press %u\n", (millis() - longPressTime)); // DEBUG_MSG("Long press %u\n", (millis() - longPressTime));
} }
} }
@ -298,6 +298,22 @@ void setup()
digitalWrite(RESET_OLED, 1); digitalWrite(RESET_OLED, 1);
#endif #endif
// If BUTTON_PIN is held down during the startup process,
// force the device to go into a SoftAP mode.
bool forceSoftAP = 0;
#ifdef BUTTON_PIN
#ifndef NO_ESP32
pinMode(BUTTON_PIN, INPUT);
// BUTTON_PIN is pulled high by a 12k resistor.
if (!digitalRead(BUTTON_PIN)) {
forceSoftAP = 1;
DEBUG_MSG("-------------------- Setting forceSoftAP = 1\n");
}
#endif
#endif
OSThread::setup(); OSThread::setup();
ledPeriodic = new Periodic("Blink", ledBlinker); ledPeriodic = new Periodic("Blink", ledBlinker);
@ -467,7 +483,7 @@ void setup()
#endif #endif
// Initialize Wifi // Initialize Wifi
initWifi(); initWifi(forceSoftAP);
if (!rIf) if (!rIf)
recordCriticalError(ErrNoRadio); recordCriticalError(ErrNoRadio);

View File

@ -56,8 +56,10 @@ void handleRoot(HTTPRequest *req, HTTPResponse *res);
void handleStaticBrowse(HTTPRequest *req, HTTPResponse *res); void handleStaticBrowse(HTTPRequest *req, HTTPResponse *res);
void handleStaticPost(HTTPRequest *req, HTTPResponse *res); void handleStaticPost(HTTPRequest *req, HTTPResponse *res);
void handleStatic(HTTPRequest *req, HTTPResponse *res); void handleStatic(HTTPRequest *req, HTTPResponse *res);
void handleRestart(HTTPRequest *req, HTTPResponse *res);
void handle404(HTTPRequest *req, HTTPResponse *res); void handle404(HTTPRequest *req, HTTPResponse *res);
void handleFormUpload(HTTPRequest *req, HTTPResponse *res); void handleFormUpload(HTTPRequest *req, HTTPResponse *res);
void handleScanNetworks(HTTPRequest *req, HTTPResponse *res);
void middlewareSpeedUp240(HTTPRequest *req, HTTPResponse *res, std::function<void()> next); void middlewareSpeedUp240(HTTPRequest *req, HTTPResponse *res, std::function<void()> next);
void middlewareSpeedUp160(HTTPRequest *req, HTTPResponse *res, std::function<void()> next); void middlewareSpeedUp160(HTTPRequest *req, HTTPResponse *res, std::function<void()> next);
@ -70,10 +72,11 @@ uint32_t timeSpeedUp = 0;
// We need to specify some content-type mapping, so the resources get delivered with the // We need to specify some content-type mapping, so the resources get delivered with the
// right content type and are displayed correctly in the browser // right content type and are displayed correctly in the browser
char contentTypes[][2][32] = {{".txt", "text/plain"}, {".html", "text/html"}, {".js", "text/javascript"}, char contentTypes[][2][32] = {{".txt", "text/plain"}, {".html", "text/html"},
{".png", "image/png"}, {".jpg", "image/jpg"}, {".gz", "application/gzip"}, {".js", "text/javascript"}, {".png", "image/png"},
{".gif", "image/gif"}, {".json", "application/json"}, {".css", "text/css"}, {".jpg", "image/jpg"}, {".gz", "application/gzip"},
{"", ""}}; {".gif", "image/gif"}, {".json", "application/json"},
{".css", "text/css"}, {"", ""}};
void handleWebResponse() void handleWebResponse()
{ {
@ -175,9 +178,10 @@ void createSSLCert()
NULL); /* Task handle. */ NULL); /* Task handle. */
DEBUG_MSG("Waiting for SSL Cert to be generated.\n"); DEBUG_MSG("Waiting for SSL Cert to be generated.\n");
if (isCertReady) { while (!isCertReady) {
DEBUG_MSG(".\n"); DEBUG_MSG(".");
delayMicroseconds(1000); delay(1000);
yield();
} }
DEBUG_MSG("SSL Cert Ready!\n"); DEBUG_MSG("SSL Cert Ready!\n");
} }
@ -233,8 +237,10 @@ void initWebServer()
ResourceNode *nodeStaticBrowse = new ResourceNode("/static", "GET", &handleStaticBrowse); ResourceNode *nodeStaticBrowse = new ResourceNode("/static", "GET", &handleStaticBrowse);
ResourceNode *nodeStaticPOST = new ResourceNode("/static", "POST", &handleStaticPost); ResourceNode *nodeStaticPOST = new ResourceNode("/static", "POST", &handleStaticPost);
ResourceNode *nodeStatic = new ResourceNode("/static/*", "GET", &handleStatic); ResourceNode *nodeStatic = new ResourceNode("/static/*", "GET", &handleStatic);
ResourceNode *nodeRestart = new ResourceNode("/restart", "POST", &handleRestart);
ResourceNode *node404 = new ResourceNode("", "GET", &handle404); ResourceNode *node404 = new ResourceNode("", "GET", &handle404);
ResourceNode *nodeFormUpload = new ResourceNode("/upload", "POST", &handleFormUpload); ResourceNode *nodeFormUpload = new ResourceNode("/upload", "POST", &handleFormUpload);
ResourceNode *nodeJsonScanNetworks = new ResourceNode("/json/scanNetworks", "GET", &handleScanNetworks);
// Secure nodes // Secure nodes
secureServer->registerNode(nodeAPIv1ToRadioOptions); secureServer->registerNode(nodeAPIv1ToRadioOptions);
@ -246,8 +252,10 @@ void initWebServer()
secureServer->registerNode(nodeStaticBrowse); secureServer->registerNode(nodeStaticBrowse);
secureServer->registerNode(nodeStaticPOST); secureServer->registerNode(nodeStaticPOST);
secureServer->registerNode(nodeStatic); secureServer->registerNode(nodeStatic);
secureServer->registerNode(nodeRestart);
secureServer->setDefaultNode(node404); secureServer->setDefaultNode(node404);
secureServer->setDefaultNode(nodeFormUpload); secureServer->setDefaultNode(nodeFormUpload);
secureServer->setDefaultNode(nodeJsonScanNetworks);
secureServer->addMiddleware(&middlewareSpeedUp240); secureServer->addMiddleware(&middlewareSpeedUp240);
@ -261,8 +269,10 @@ void initWebServer()
insecureServer->registerNode(nodeStaticBrowse); insecureServer->registerNode(nodeStaticBrowse);
insecureServer->registerNode(nodeStaticPOST); insecureServer->registerNode(nodeStaticPOST);
insecureServer->registerNode(nodeStatic); insecureServer->registerNode(nodeStatic);
insecureServer->registerNode(nodeRestart);
insecureServer->setDefaultNode(node404); insecureServer->setDefaultNode(node404);
insecureServer->setDefaultNode(nodeFormUpload); insecureServer->setDefaultNode(nodeFormUpload);
insecureServer->setDefaultNode(nodeJsonScanNetworks);
insecureServer->addMiddleware(&middlewareSpeedUp160); insecureServer->addMiddleware(&middlewareSpeedUp160);
@ -512,7 +522,6 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res)
// Get access to the parameters // Get access to the parameters
ResourceParameters *params = req->getParams(); ResourceParameters *params = req->getParams();
std::string parameter1; std::string parameter1;
// Print the first parameter value // Print the first parameter value
if (params->getPathParameter(0, parameter1)) { if (params->getPathParameter(0, parameter1)) {
@ -560,7 +569,7 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res)
cTypeIdx += 1; cTypeIdx += 1;
} while (strlen(contentTypes[cTypeIdx][0]) > 0); } while (strlen(contentTypes[cTypeIdx][0]) > 0);
if(!has_set_content_type) { if (!has_set_content_type) {
// Set a default content type // Set a default content type
res->setHeader("Content-Type", "application/octet-stream"); res->setHeader("Content-Type", "application/octet-stream");
} }
@ -845,9 +854,9 @@ void handleRoot(HTTPRequest *req, HTTPResponse *res)
"mt_session=" + httpsserver::intToString(random(1, 9999999)) + "; Expires=Wed, 20 Apr 2049 4:20:00 PST"); "mt_session=" + httpsserver::intToString(random(1, 9999999)) + "; Expires=Wed, 20 Apr 2049 4:20:00 PST");
std::string cookie = req->getHeader("Cookie"); std::string cookie = req->getHeader("Cookie");
//String cookieString = cookie.c_str(); // String cookieString = cookie.c_str();
//uint8_t nameIndex = cookieString.indexOf("mt_session"); // uint8_t nameIndex = cookieString.indexOf("mt_session");
//DEBUG_MSG(cookie.c_str()); // DEBUG_MSG(cookie.c_str());
std::string filename = "/static/index.html"; std::string filename = "/static/index.html";
std::string filenameGzip = "/static/index.html.gz"; std::string filenameGzip = "/static/index.html.gz";
@ -860,7 +869,8 @@ void handleRoot(HTTPRequest *req, HTTPResponse *res)
res->printf("<p>File not found: %s</p>\n", filename.c_str()); res->printf("<p>File not found: %s</p>\n", filename.c_str());
res->printf("<p></p>\n"); res->printf("<p></p>\n");
res->printf("<p>You have gotten this error because the filesystem for the web server has not been loaded.</p>\n"); res->printf("<p>You have gotten this error because the filesystem for the web server has not been loaded.</p>\n");
res->printf("<p>Please review the 'Common Problems' section of the <a href=https://github.com/meshtastic/Meshtastic-device/issues/552>web interface</a> documentation.</p>\n"); res->printf("<p>Please review the 'Common Problems' section of the <a "
"href=https://github.com/meshtastic/Meshtastic-device/issues/552>web interface</a> documentation.</p>\n");
return; return;
} }
@ -881,7 +891,6 @@ void handleRoot(HTTPRequest *req, HTTPResponse *res)
} }
} }
// Read the file from SPIFFS and write it to the HTTP response body // Read the file from SPIFFS and write it to the HTTP response body
size_t length = 0; size_t length = 0;
do { do {
@ -892,6 +901,61 @@ void handleRoot(HTTPRequest *req, HTTPResponse *res)
} while (length > 0); } while (length > 0);
} }
void handleRestart(HTTPRequest *req, HTTPResponse *res)
{
res->setHeader("Content-Type", "text/html");
DEBUG_MSG("***** Restarted on HTTP(s) Request *****\n");
res->println("Restarting");
ESP.restart();
}
void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
{
res->setHeader("Content-Type", "application/json");
// res->setHeader("Content-Type", "text/html");
int n = WiFi.scanNetworks();
res->println("{");
res->println("\"data\": {");
if (n == 0) {
// No networks found.
res->println("\"networks\": []");
} else {
res->println("\"networks\": [");
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());
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->printf(",");
}
}
// Yield some cpu cycles to IP stack.
// This is important in case the list is large and it takes us time to return
// to the main loop.
yield();
}
res->println("]");
}
res->println("},");
res->println("\"status\": \"ok\"");
res->println("}");
}
void handleFavicon(HTTPRequest *req, HTTPResponse *res) void handleFavicon(HTTPRequest *req, HTTPResponse *res)
{ {
// Set Content-Type // Set Content-Type
@ -900,7 +964,6 @@ void handleFavicon(HTTPRequest *req, HTTPResponse *res)
res->write(FAVICON_DATA, FAVICON_LENGTH); res->write(FAVICON_DATA, FAVICON_LENGTH);
} }
void replaceAll(std::string &str, const std::string &from, const std::string &to) void replaceAll(std::string &str, const std::string &from, const std::string &to)
{ {
if (from.empty()) if (from.empty())
@ -911,4 +974,3 @@ void replaceAll(std::string &str, const std::string &from, const std::string &to
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
} }
} }

View File

@ -21,14 +21,32 @@ uint8_t wifiDisconnectReason = 0;
// Stores our hostname // Stores our hostname
char ourHost[16]; char ourHost[16];
bool forcedSoftAP = 0;
bool APStartupComplete = 0;
bool isSoftAPForced()
{
return forcedSoftAP;
}
bool isWifiAvailable() bool isWifiAvailable()
{ {
// If wifi status is connected, return true regardless of the radio configuration.
if (isSoftAPForced()) {
return 1;
}
const char *wifiName = radioConfig.preferences.wifi_ssid; const char *wifiName = radioConfig.preferences.wifi_ssid;
const char *wifiPsw = radioConfig.preferences.wifi_password; const char *wifiPsw = radioConfig.preferences.wifi_password;
// strcpy(radioConfig.preferences.wifi_ssid, ""); // strcpy(radioConfig.preferences.wifi_ssid, "");
// strcpy(radioConfig.preferences.wifi_password, ""); // strcpy(radioConfig.preferences.wifi_password, "");
// strcpy(radioConfig.preferences.wifi_ssid, "meshtasticAdmin");
// strcpy(radioConfig.preferences.wifi_password, "12345678");
// radioConfig.preferences.wifi_ap_mode = true;
if (*wifiName && *wifiPsw) { if (*wifiName && *wifiPsw) {
return 1; return 1;
} else { } else {
@ -58,20 +76,44 @@ void deinitWifi()
} }
// Startup WiFi // Startup WiFi
void initWifi() void initWifi(bool forceSoftAP)
{ {
if (isWifiAvailable() == 0) {
return; if (forceSoftAP) {
// do nothing
// DEBUG_MSG("----- Forcing SoftAP\n");
} else {
if (isWifiAvailable() == 0) {
return;
}
} }
forcedSoftAP = forceSoftAP;
createSSLCert(); createSSLCert();
if (radioConfig.has_preferences) { if (radioConfig.has_preferences || forceSoftAP) {
const char *wifiName = radioConfig.preferences.wifi_ssid; const char *wifiName = radioConfig.preferences.wifi_ssid;
const char *wifiPsw = radioConfig.preferences.wifi_password; const char *wifiPsw = radioConfig.preferences.wifi_password;
if (*wifiName && *wifiPsw) { if ((*wifiName && *wifiPsw) || forceSoftAP) {
if (radioConfig.preferences.wifi_ap_mode) { if (forceSoftAP) {
DEBUG_MSG("Forcing SoftAP\n");
const char *softAPssid = "meshtasticAdmin";
const char *softAPpasswd = "12345678";
IPAddress apIP(192, 168, 42, 1);
WiFi.onEvent(WiFiEvent);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
DEBUG_MSG("STARTING WIFI AP: ssid=%s, ok=%d\n", softAPssid, WiFi.softAP(softAPssid, softAPpasswd));
DEBUG_MSG("MY IP ADDRESS: %s\n", WiFi.softAPIP().toString().c_str());
dnsServer.start(53, "*", apIP);
} else if (radioConfig.preferences.wifi_ap_mode) {
IPAddress apIP(192, 168, 42, 1); IPAddress apIP(192, 168, 42, 1);
WiFi.onEvent(WiFiEvent); WiFi.onEvent(WiFiEvent);
@ -203,9 +245,16 @@ static void WiFiEvent(WiFiEvent_t event)
DEBUG_MSG("WiFi access point started\n"); DEBUG_MSG("WiFi access point started\n");
Serial.println(WiFi.softAPIP()); Serial.println(WiFi.softAPIP());
// Start web server if (!APStartupComplete) {
initWebServer(); // Start web server
initApiServer(); DEBUG_MSG("... Starting network services\n");
initWebServer();
initApiServer();
APStartupComplete = true;
} else {
DEBUG_MSG("... Not starting network services\n");
}
break; break;
case SYSTEM_EVENT_AP_STOP: case SYSTEM_EVENT_AP_STOP:

View File

@ -9,7 +9,7 @@
#include <WiFi.h> #include <WiFi.h>
#endif #endif
void initWifi(); void initWifi(bool forceSoftAP);
void deinitWifi(); void deinitWifi();
bool isWifiAvailable(); bool isWifiAvailable();
@ -18,5 +18,7 @@ void handleDNSResponse();
void reconnectWiFi(); void reconnectWiFi();
bool isSoftAPForced();
uint8_t getWifiDisconnectReason(); uint8_t getWifiDisconnectReason();

View File

@ -545,7 +545,7 @@ void setBluetoothEnable(bool on)
if (firstTime) { if (firstTime) {
firstTime = 0; firstTime = 0;
} else { } else {
initWifi(); initWifi(0);
} }
} else { } else {

View File

@ -1,7 +1,7 @@
#include "meshwifi/meshhttp.h" #include "meshwifi/meshhttp.h"
#include "meshwifi/meshwifi.h" #include "meshwifi/meshwifi.h"
void initWifi() {} void initWifi(bool forceSoftAP) {}
void deinitWifi() {} void deinitWifi() {}