From f129b458adc5c159f1de47057e057f50255087c2 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sat, 12 Sep 2020 21:43:41 -0700 Subject: [PATCH 01/34] Initial Checkin for WiFi and HTTP Server Framework --- src/configuration.h | 15 +++ src/graphics/Screen.cpp | 38 +++++++ src/graphics/Screen.h | 4 + src/main.cpp | 11 ++ src/main.h | 4 +- src/mesh/NodeDB.cpp | 6 + src/meshwifi/meshwifi.cpp | 212 +++++++++++++++++++++++++++++++++++ src/meshwifi/meshwifi.h | 22 ++++ src/nimble/BluetoothUtil.cpp | 33 +----- 9 files changed, 314 insertions(+), 31 deletions(-) create mode 100644 src/meshwifi/meshwifi.cpp create mode 100644 src/meshwifi/meshwifi.h diff --git a/src/configuration.h b/src/configuration.h index e70f1fda4..e2098fd0d 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -397,3 +397,18 @@ along with this program. If not, see . #define GPS_POWER_CTRL_CH 3 #define LORA_POWER_CTRL_CH 2 + +// ----------------------------------------------------------------------------- +// WiFi Configuration +// ----------------------------------------------------------------------------- +// +// Set WiFi credentials using the API (Does this work?) +// meshtastic --setpref WiFi_SSID_NAME yournetwork +// meshtastic --setpref WiFi_SSID_PASSWORD yourpassword +// +// WiFi_Mode +// 0 = Disabled +// 1 = Enabled +#define WiFi_MODE 0 +#define WiFi_SSID_NAME "meshtastic" +#define WiFi_SSID_PASSWORD "meshtastic!" \ No newline at end of file diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 5229f5660..4a6418b9e 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -32,6 +32,7 @@ along with this program. If not, see . #include "main.h" #include "mesh-pb-constants.h" #include "utils.h" +#include using namespace meshtastic; /** @todo remove */ @@ -708,6 +709,12 @@ void Screen::drawDebugInfoSettingsTrampoline(OLEDDisplay *display, OLEDDisplayUi screen->debugInfo.drawFrameSettings(display, state, x, y); } +void Screen::drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) +{ + Screen *screen = reinterpret_cast(state->userData); + screen->debugInfo.drawFrameWiFi(display, state, x, y); +} + // restore our regular frame list void Screen::setFrames() @@ -739,6 +746,11 @@ void Screen::setFrames() // call a method on debugInfoScreen object (for more details) normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline; +#if WiFi_MODE + // call a method on debugInfoScreen object (for more details) + normalFrames[numframes++] = &Screen::drawDebugInfoWiFiTrampoline; +#endif + ui.setFrames(normalFrames, numframes); ui.enableAllIndicators(); @@ -827,6 +839,32 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 } // Jm +void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) +{ + displayedNodeNum = 0; // Not currently showing a node pane + + display->setFont(ArialMT_Plain_10); + + // The coordinates define the left starting point of the text + display->setTextAlignment(TEXT_ALIGN_LEFT); + + if ( WiFi.status() != WL_CONNECTED ) { + display->drawString(x, y, String("WiFi - Not Connected")); + } else { + display->drawString(x, y, String("WiFi - Connected")); + } + + display->drawString(x, y + FONT_HEIGHT * 1, WiFi.localIP().toString().c_str()); + + /* Display a heartbeat pixel that blinks every time the frame is redrawn */ +#ifdef SHOW_REDRAWS + if (heartbeat) + display->setPixel(0, 0); + heartbeat = !heartbeat; +#endif +} + + void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { displayedNodeNum = 0; // Not currently showing a node pane diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index c9ab85449..8f5a6de2a 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -17,6 +17,7 @@ #include "concurrency/PeriodicTask.h" #include "power.h" #include +#include namespace graphics { @@ -46,6 +47,7 @@ class DebugInfo /// Renders the debug screen. void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); void drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); + void drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); std::string channelName; @@ -220,6 +222,8 @@ class Screen : public concurrency::PeriodicTask static void drawDebugInfoSettingsTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); + static void drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); + /// Queue of commands to execute in doTask. TypedQueue cmdQueue; /// Whether we are using a display diff --git a/src/main.cpp b/src/main.cpp index f7af6d232..13b28debf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,6 +41,7 @@ #include "timing.h" #include #include +#include "meshwifi/meshwifi.h" // #include #ifndef NO_ESP32 @@ -325,6 +326,11 @@ void setup() } #endif +#if WiFi_MODE + // Initialize Wifi + initWifi(); +#endif + if (!rIf) recordCriticalError(ErrNoRadio); else @@ -416,5 +422,10 @@ void loop() // feel slow msecstosleep = 10; +#if WiFi_MODE + // TODO: This should go into a thread handled by FreeRTOS. + handleWebResponse(); +#endif + delay(msecstosleep); } diff --git a/src/main.h b/src/main.h index fb64d9ff0..39b1364f6 100644 --- a/src/main.h +++ b/src/main.h @@ -10,6 +10,8 @@ extern bool ssd1306_found; extern bool isCharging; extern bool isUSBPowered; + + // Global Screen singleton. extern graphics::Screen screen; //extern Observable newPowerStatus; //TODO: move this to main-esp32.cpp somehow or a helper class @@ -23,4 +25,4 @@ const char *getDeviceName(); void getMacAddr(uint8_t *dmac); -void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(); \ No newline at end of file +void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(); diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 93d0787d3..22d4675a3 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -15,6 +15,7 @@ #include "mesh-pb-constants.h" #include #include +#include "meshwifi/meshwifi.h" NodeDB nodeDB; @@ -399,6 +400,11 @@ void NodeDB::updateFrom(const MeshPacket &mp) updateTextMessage = true; powerFSM.trigger(EVENT_RECEIVED_TEXT_MSG); notifyObservers(true); // Force an update whether or not our node counts have changed + +// Only update the WebUI if WiFi is enabled +#if WiFi_MODE != 0 + notifyWebUI(); +#endif } } break; diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp new file mode 100644 index 000000000..254c852d9 --- /dev/null +++ b/src/meshwifi/meshwifi.cpp @@ -0,0 +1,212 @@ +#include "meshwifi.h" +#include +#include "configuration.h" +#include "main.h" +#include "NodeDB.h" +#include + +WebServer webserver(80); + +String something = ""; +String sender = ""; + +void initWebServer() { + webserver.onNotFound(handleNotFound); + webserver.on("/", handleJSONChatHistory); + webserver.on("/json/chat/history", handleJSONChatHistory); + //webserver.on("/", []() { + //webserver.send(200, "text/plain", "everything is awesome!"); + //}); + webserver.begin(); + +} + +void initWifi() +{ + strcpy(radioConfig.preferences.wifi_ssid, WiFi_SSID_NAME); + strcpy(radioConfig.preferences.wifi_password, WiFi_SSID_PASSWORD); + if (radioConfig.has_preferences) { + const char *wifiName = radioConfig.preferences.wifi_ssid; + + if (*wifiName) { + const char *wifiPsw = radioConfig.preferences.wifi_password; + if (radioConfig.preferences.wifi_ap_mode) { + DEBUG_MSG("STARTING WIFI AP: ssid=%s, ok=%d\n", wifiName, WiFi.softAP(wifiName, wifiPsw)); + } else { + WiFi.mode(WIFI_MODE_STA); + WiFi.onEvent(WiFiEvent); + + DEBUG_MSG("JOINING WIFI: ssid=%s\n", wifiName); + if (WiFi.begin(wifiName, wifiPsw) == WL_CONNECTED) { + DEBUG_MSG("MY IP ADDRESS: %s\n", WiFi.localIP().toString().c_str()); + } else { + DEBUG_MSG("Started Joining WIFI\n"); + } + } + } + } else + DEBUG_MSG("Not using WIFI\n"); +} + +void WiFiEvent(WiFiEvent_t event) +{ + DEBUG_MSG("************ [WiFi-event] event: %d ************\n", event); + + switch (event) { + case SYSTEM_EVENT_WIFI_READY: + DEBUG_MSG("WiFi interface ready"); + break; + case SYSTEM_EVENT_SCAN_DONE: + DEBUG_MSG("Completed scan for access points"); + break; + case SYSTEM_EVENT_STA_START: + DEBUG_MSG("WiFi client started"); + break; + case SYSTEM_EVENT_STA_STOP: + DEBUG_MSG("WiFi clients stopped"); + break; + case SYSTEM_EVENT_STA_CONNECTED: + DEBUG_MSG("Connected to access point"); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + DEBUG_MSG("Disconnected from WiFi access point"); + + // Reconnect WiFi + reconnectWiFi(); + break; + case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: + DEBUG_MSG("Authentication mode of access point has changed"); + break; + case SYSTEM_EVENT_STA_GOT_IP: + DEBUG_MSG("Obtained IP address: "); + Serial.println(WiFi.localIP()); + + // Start web server + initWebServer(); + break; + case SYSTEM_EVENT_STA_LOST_IP: + DEBUG_MSG("Lost IP address and IP address is reset to 0"); + break; + case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: + DEBUG_MSG("WiFi Protected Setup (WPS): succeeded in enrollee mode"); + break; + case SYSTEM_EVENT_STA_WPS_ER_FAILED: + DEBUG_MSG("WiFi Protected Setup (WPS): failed in enrollee mode"); + break; + case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: + DEBUG_MSG("WiFi Protected Setup (WPS): timeout in enrollee mode"); + break; + case SYSTEM_EVENT_STA_WPS_ER_PIN: + DEBUG_MSG("WiFi Protected Setup (WPS): pin code in enrollee mode"); + break; + case SYSTEM_EVENT_AP_START: + DEBUG_MSG("WiFi access point started"); + break; + case SYSTEM_EVENT_AP_STOP: + DEBUG_MSG("WiFi access point stopped"); + break; + case SYSTEM_EVENT_AP_STACONNECTED: + DEBUG_MSG("Client connected"); + break; + case SYSTEM_EVENT_AP_STADISCONNECTED: + DEBUG_MSG("Client disconnected"); + break; + case SYSTEM_EVENT_AP_STAIPASSIGNED: + DEBUG_MSG("Assigned IP address to client"); + break; + case SYSTEM_EVENT_AP_PROBEREQRECVED: + DEBUG_MSG("Received probe request"); + break; + case SYSTEM_EVENT_GOT_IP6: + DEBUG_MSG("IPv6 is preferred"); + break; + case SYSTEM_EVENT_ETH_START: + DEBUG_MSG("Ethernet started"); + break; + case SYSTEM_EVENT_ETH_STOP: + DEBUG_MSG("Ethernet stopped"); + break; + case SYSTEM_EVENT_ETH_CONNECTED: + DEBUG_MSG("Ethernet connected"); + break; + case SYSTEM_EVENT_ETH_DISCONNECTED: + DEBUG_MSG("Ethernet disconnected"); + break; + case SYSTEM_EVENT_ETH_GOT_IP: + DEBUG_MSG("Obtained IP address"); + break; + default: break; + } +} + +void handleJSONChatHistory() { + + String out = ""; + out += "{\n"; + out += " \"data\" : {\n"; + out += " \"chat\" : "; + out += "["; + out += "\"" + sender + "\""; + out += ","; + out += "\"" + something + "\""; + out += "]\n"; + + + + out += "\n"; + out += " }\n"; + out += "}\n"; + + webserver.send ( 200, "application/json", out ); + return; + + +} + +void handleWebResponse() { + webserver.handleClient(); +} + + +void handleNotFound() { + String 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"; + } + + webserver.send(404, "text/plain", message); + /* + */ +} + +void reconnectWiFi() { + if ( WiFi.status() != WL_CONNECTED ) { + DEBUG_MSG("... Reconnecting to WiFi access point"); + WiFi.begin( ); + } + +} + + +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; + +} \ No newline at end of file diff --git a/src/meshwifi/meshwifi.h b/src/meshwifi/meshwifi.h new file mode 100644 index 000000000..e6b456e22 --- /dev/null +++ b/src/meshwifi/meshwifi.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include + +void handleNotFound(); + +void reconnectWiFi(); + +void initWifi(); + +void initWebServer(); + +void handleWebResponse(); + +void notifyWebUI(); + +void handleJSONChatHistory(); + +void WiFiEvent(WiFiEvent_t event); + diff --git a/src/nimble/BluetoothUtil.cpp b/src/nimble/BluetoothUtil.cpp index 490bc13d4..20b5aace4 100644 --- a/src/nimble/BluetoothUtil.cpp +++ b/src/nimble/BluetoothUtil.cpp @@ -1,10 +1,9 @@ #include "BluetoothUtil.h" #include "BluetoothSoftwareUpdate.h" #include "NimbleBluetoothAPI.h" -#include "NodeDB.h" // FIXME - we shouldn't really douch this here - we are using it only because we currently do wifi setup when ble gets turned on #include "PhoneAPI.h" #include "PowerFSM.h" -#include "WiFi.h" +#include #include "configuration.h" #include "esp_bt.h" #include "host/util/util.h" @@ -503,32 +502,6 @@ void reinitBluetooth() nimble_port_freertos_init(ble_host_task); } -void initWifi() -{ - // Note: Wifi is not yet supported ;-) - strcpy(radioConfig.preferences.wifi_ssid, ""); - strcpy(radioConfig.preferences.wifi_password, ""); - if (radioConfig.has_preferences) { - const char *wifiName = radioConfig.preferences.wifi_ssid; - - if (*wifiName) { - const char *wifiPsw = radioConfig.preferences.wifi_password; - if (radioConfig.preferences.wifi_ap_mode) { - DEBUG_MSG("STARTING WIFI AP: ssid=%s, ok=%d\n", wifiName, WiFi.softAP(wifiName, wifiPsw)); - } else { - WiFi.mode(WIFI_MODE_STA); - DEBUG_MSG("JOINING WIFI: ssid=%s\n", wifiName); - if (WiFi.begin(wifiName, wifiPsw) == WL_CONNECTED) { - DEBUG_MSG("MY IP ADDRESS: %s\n", WiFi.localIP().toString().c_str()); - } else { - DEBUG_MSG("Started Joining WIFI\n"); - } - } - } - } else - DEBUG_MSG("Not using WIFI\n"); -} - bool bluetoothOn; // Enable/disable bluetooth. @@ -542,11 +515,11 @@ void setBluetoothEnable(bool on) Serial.printf("Pre BT: %u heap size\n", ESP.getFreeHeap()); // ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) ); reinitBluetooth(); - initWifi(); + //initWifi(); } else { // We have to totally teardown our bluetooth objects to prevent leaks deinitBLE(); - WiFi.mode(WIFI_MODE_NULL); // shutdown wifi + //WiFi.mode(WIFI_MODE_NULL); // shutdown wifi Serial.printf("Shutdown BT: %u heap size\n", ESP.getFreeHeap()); // ESP_ERROR_CHECK( heap_trace_stop() ); // heap_trace_dump(); From e508306395b7f55f35d082e9a213f3db311638c9 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sun, 13 Sep 2020 16:58:36 -0700 Subject: [PATCH 02/34] Refactoring to break out HTTP from WiFi --- src/graphics/Screen.cpp | 6 +++ src/main.cpp | 12 +++++- src/mesh/NodeDB.cpp | 7 +-- src/meshwifi/meshhttp.cpp | 89 +++++++++++++++++++++++++++++++++++++++ src/meshwifi/meshhttp.h | 16 +++++++ src/meshwifi/meshwifi.cpp | 82 +----------------------------------- src/meshwifi/meshwifi.h | 10 ----- 7 files changed, 127 insertions(+), 95 deletions(-) create mode 100644 src/meshwifi/meshhttp.cpp create mode 100644 src/meshwifi/meshhttp.h diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 4a6418b9e..e14e4078e 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -841,6 +841,9 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 // Jm void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { + const char *wifiName = radioConfig.preferences.wifi_ssid; + const char *wifiPsw = radioConfig.preferences.wifi_password; + displayedNodeNum = 0; // Not currently showing a node pane display->setFont(ArialMT_Plain_10); @@ -856,6 +859,9 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i display->drawString(x, y + FONT_HEIGHT * 1, WiFi.localIP().toString().c_str()); + display->drawString(x, y + FONT_HEIGHT * 2, wifiName); + display->drawString(x, y + FONT_HEIGHT * 3, wifiPsw); + /* Display a heartbeat pixel that blinks every time the frame is redrawn */ #ifdef SHOW_REDRAWS if (heartbeat) diff --git a/src/main.cpp b/src/main.cpp index 13b28debf..5c5a3a0e1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -42,6 +42,7 @@ #include #include #include "meshwifi/meshwifi.h" +#include "meshwifi/meshhttp.h" // #include #ifndef NO_ESP32 @@ -426,6 +427,15 @@ void loop() // TODO: This should go into a thread handled by FreeRTOS. handleWebResponse(); #endif - +/* + const char *wifiName = radioConfig.preferences.wifi_ssid; + const char *wifiPsw = radioConfig.preferences.wifi_password; + Serial.print("-------------------"); + Serial.print(wifiName); + Serial.print(" "); + Serial.println(wifiPsw); + Serial.println("+++++++++++++++++++"); + Serial.println(""); +*/ delay(msecstosleep); } diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 22d4675a3..07a97acfb 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -401,10 +401,11 @@ void NodeDB::updateFrom(const MeshPacket &mp) powerFSM.trigger(EVENT_RECEIVED_TEXT_MSG); notifyObservers(true); // Force an update whether or not our node counts have changed +// This is going into the wifidev feature branch // Only update the WebUI if WiFi is enabled -#if WiFi_MODE != 0 - notifyWebUI(); -#endif +//#if WiFi_MODE != 0 +// notifyWebUI(); +//#endif } } break; diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp new file mode 100644 index 000000000..b70b8fc29 --- /dev/null +++ b/src/meshwifi/meshhttp.cpp @@ -0,0 +1,89 @@ +#include +#include +#include "configuration.h" +#include "main.h" +#include "NodeDB.h" +#include "meshwifi.h" +#include "meshhttp.h" + + +WebServer webserver(80); + +String something = ""; +String sender = ""; + + +void handleWebResponse() { + webserver.handleClient(); +} + +void initWebServer() { + webserver.onNotFound(handleNotFound); + //webserver.on("/", handleJSONChatHistory); + //webserver.on("/json/chat/history", handleJSONChatHistory); + webserver.on("/", []() { + webserver.send(200, "text/plain", "Everything is awesome!"); + }); + webserver.begin(); + +} + + +void handleJSONChatHistory() { + + String out = ""; + out += "{\n"; + out += " \"data\" : {\n"; + out += " \"chat\" : "; + out += "["; + out += "\"" + sender + "\""; + out += ","; + out += "\"" + something + "\""; + out += "]\n"; + + + + out += "\n"; + out += " }\n"; + out += "}\n"; + + webserver.send ( 200, "application/json", out ); + return; + +} + +void handleNotFound() { + String 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"; + } + + webserver.send(404, "text/plain", message); + /* + */ +} + + + +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; + +} \ No newline at end of file diff --git a/src/meshwifi/meshhttp.h b/src/meshwifi/meshhttp.h new file mode 100644 index 000000000..cbff51db7 --- /dev/null +++ b/src/meshwifi/meshhttp.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include +#include + +void initWebServer(); + +void handleNotFound(); + +void handleWebResponse(); + +void handleJSONChatHistory(); + +void notifyWebUI(); + diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index 254c852d9..ea7df5c73 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -3,23 +3,7 @@ #include "configuration.h" #include "main.h" #include "NodeDB.h" -#include - -WebServer webserver(80); - -String something = ""; -String sender = ""; - -void initWebServer() { - webserver.onNotFound(handleNotFound); - webserver.on("/", handleJSONChatHistory); - webserver.on("/json/chat/history", handleJSONChatHistory); - //webserver.on("/", []() { - //webserver.send(200, "text/plain", "everything is awesome!"); - //}); - webserver.begin(); - -} +#include "meshwifi/meshhttp.h" void initWifi() { @@ -139,54 +123,6 @@ void WiFiEvent(WiFiEvent_t event) } } -void handleJSONChatHistory() { - - String out = ""; - out += "{\n"; - out += " \"data\" : {\n"; - out += " \"chat\" : "; - out += "["; - out += "\"" + sender + "\""; - out += ","; - out += "\"" + something + "\""; - out += "]\n"; - - - - out += "\n"; - out += " }\n"; - out += "}\n"; - - webserver.send ( 200, "application/json", out ); - return; - - -} - -void handleWebResponse() { - webserver.handleClient(); -} - - -void handleNotFound() { - String 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"; - } - - webserver.send(404, "text/plain", message); - /* - */ -} - void reconnectWiFi() { if ( WiFi.status() != WL_CONNECTED ) { DEBUG_MSG("... Reconnecting to WiFi access point"); @@ -194,19 +130,3 @@ void reconnectWiFi() { } } - - -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; - -} \ No newline at end of file diff --git a/src/meshwifi/meshwifi.h b/src/meshwifi/meshwifi.h index e6b456e22..97903397f 100644 --- a/src/meshwifi/meshwifi.h +++ b/src/meshwifi/meshwifi.h @@ -4,19 +4,9 @@ #include #include -void handleNotFound(); - void reconnectWiFi(); void initWifi(); -void initWebServer(); - -void handleWebResponse(); - -void notifyWebUI(); - -void handleJSONChatHistory(); - void WiFiEvent(WiFiEvent_t event); From f5c939fb10469d31fcdc922345878c1e2703fabb Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sun, 13 Sep 2020 22:22:49 -0700 Subject: [PATCH 03/34] Fix to turn WiFi back on after the bluetooth radio is reenabled. --- src/main.cpp | 11 +---------- src/meshwifi/meshwifi.cpp | 17 +++++++++++++---- src/nimble/BluetoothUtil.cpp | 9 ++++++++- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5c5a3a0e1..81038030d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -427,15 +427,6 @@ void loop() // TODO: This should go into a thread handled by FreeRTOS. handleWebResponse(); #endif -/* - const char *wifiName = radioConfig.preferences.wifi_ssid; - const char *wifiPsw = radioConfig.preferences.wifi_password; - Serial.print("-------------------"); - Serial.print(wifiName); - Serial.print(" "); - Serial.println(wifiPsw); - Serial.println("+++++++++++++++++++"); - Serial.println(""); -*/ + delay(msecstosleep); } diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index ea7df5c73..460511664 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -32,6 +32,7 @@ void initWifi() DEBUG_MSG("Not using WIFI\n"); } + void WiFiEvent(WiFiEvent_t event) { DEBUG_MSG("************ [WiFi-event] event: %d ************\n", event); @@ -124,9 +125,17 @@ void WiFiEvent(WiFiEvent_t event) } void reconnectWiFi() { - if ( WiFi.status() != WL_CONNECTED ) { - DEBUG_MSG("... Reconnecting to WiFi access point"); - WiFi.begin( ); - } + const char *wifiName = radioConfig.preferences.wifi_ssid; + const char *wifiPsw = radioConfig.preferences.wifi_password; + if (radioConfig.has_preferences) { + + if (*wifiName) { + + DEBUG_MSG("... Reconnecting to WiFi access point"); + + WiFi.mode(WIFI_MODE_STA); + WiFi.begin(wifiName, wifiPsw); + } + } } diff --git a/src/nimble/BluetoothUtil.cpp b/src/nimble/BluetoothUtil.cpp index 20b5aace4..059b2ec22 100644 --- a/src/nimble/BluetoothUtil.cpp +++ b/src/nimble/BluetoothUtil.cpp @@ -12,6 +12,7 @@ #include "services/gap/ble_svc_gap.h" #include "services/gatt/ble_svc_gatt.h" #include +#include "meshwifi/meshwifi.h" static bool pinShowing; @@ -503,6 +504,7 @@ void reinitBluetooth() } bool bluetoothOn; +bool firstTime = 1; // Enable/disable bluetooth. void setBluetoothEnable(bool on) @@ -515,7 +517,12 @@ void setBluetoothEnable(bool on) Serial.printf("Pre BT: %u heap size\n", ESP.getFreeHeap()); // ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) ); reinitBluetooth(); - //initWifi(); + + if (firstTime) { + firstTime = 0; + } else { + reconnectWiFi(); + } } else { // We have to totally teardown our bluetooth objects to prevent leaks deinitBLE(); From 066d9d48a41b814b0b87637d51e617252c6a91ff Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Mon, 14 Sep 2020 20:27:49 -0700 Subject: [PATCH 04/34] New method to deinit the wifi stack. --- src/meshwifi/meshwifi.cpp | 7 +++++++ src/meshwifi/meshwifi.h | 2 ++ src/nimble/BluetoothUtil.cpp | 5 ++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index 460511664..8c5d0a2ae 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -5,6 +5,12 @@ #include "NodeDB.h" #include "meshwifi/meshhttp.h" +void deinitWifi() +{ + WiFi.mode(WIFI_MODE_NULL); + DEBUG_MSG("WiFi Turned Off\n"); +} + void initWifi() { strcpy(radioConfig.preferences.wifi_ssid, WiFi_SSID_NAME); @@ -68,6 +74,7 @@ void WiFiEvent(WiFiEvent_t event) // Start web server initWebServer(); + break; case SYSTEM_EVENT_STA_LOST_IP: DEBUG_MSG("Lost IP address and IP address is reset to 0"); diff --git a/src/meshwifi/meshwifi.h b/src/meshwifi/meshwifi.h index 97903397f..a20a114aa 100644 --- a/src/meshwifi/meshwifi.h +++ b/src/meshwifi/meshwifi.h @@ -8,5 +8,7 @@ void reconnectWiFi(); void initWifi(); +void deinitWifi(); + void WiFiEvent(WiFiEvent_t event); diff --git a/src/nimble/BluetoothUtil.cpp b/src/nimble/BluetoothUtil.cpp index 059b2ec22..f5595c5a9 100644 --- a/src/nimble/BluetoothUtil.cpp +++ b/src/nimble/BluetoothUtil.cpp @@ -518,6 +518,8 @@ void setBluetoothEnable(bool on) // ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) ); reinitBluetooth(); + // Don't try to reconnect wifi before bluetooth is configured. + // WiFi is initialized from main.cpp in setup() . if (firstTime) { firstTime = 0; } else { @@ -526,7 +528,8 @@ void setBluetoothEnable(bool on) } else { // We have to totally teardown our bluetooth objects to prevent leaks deinitBLE(); - //WiFi.mode(WIFI_MODE_NULL); // shutdown wifi + WiFi.mode(WIFI_MODE_NULL); // shutdown wifi + Serial.printf("Shutdown BT: %u heap size\n", ESP.getFreeHeap()); // ESP_ERROR_CHECK( heap_trace_stop() ); // heap_trace_dump(); From 3fcd4a61aaf5ccc6b6a00459f0dc6e03eee1fae2 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Tue, 15 Sep 2020 20:24:03 -0700 Subject: [PATCH 05/34] commenting out the strcpy to manually set the wifi info. --- src/meshwifi/meshwifi.cpp | 4 ++-- src/nimble/BluetoothUtil.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index 8c5d0a2ae..19a52bf51 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -13,8 +13,8 @@ void deinitWifi() void initWifi() { - strcpy(radioConfig.preferences.wifi_ssid, WiFi_SSID_NAME); - strcpy(radioConfig.preferences.wifi_password, WiFi_SSID_PASSWORD); + //strcpy(radioConfig.preferences.wifi_ssid, WiFi_SSID_NAME); + //strcpy(radioConfig.preferences.wifi_password, WiFi_SSID_PASSWORD); if (radioConfig.has_preferences) { const char *wifiName = radioConfig.preferences.wifi_ssid; diff --git a/src/nimble/BluetoothUtil.cpp b/src/nimble/BluetoothUtil.cpp index f5595c5a9..00e7deea1 100644 --- a/src/nimble/BluetoothUtil.cpp +++ b/src/nimble/BluetoothUtil.cpp @@ -528,7 +528,7 @@ void setBluetoothEnable(bool on) } else { // We have to totally teardown our bluetooth objects to prevent leaks deinitBLE(); - WiFi.mode(WIFI_MODE_NULL); // shutdown wifi + deinitWifi(); // shutdown wifi Serial.printf("Shutdown BT: %u heap size\n", ESP.getFreeHeap()); // ESP_ERROR_CHECK( heap_trace_stop() ); From 27ad8472c14f7975a4665708ab04949c88dbde3c Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Tue, 15 Sep 2020 20:24:58 -0700 Subject: [PATCH 06/34] remove ssid info from configuration.h --- src/configuration.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/configuration.h b/src/configuration.h index e2098fd0d..63d1dbfc4 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -409,6 +409,4 @@ along with this program. If not, see . // WiFi_Mode // 0 = Disabled // 1 = Enabled -#define WiFi_MODE 0 -#define WiFi_SSID_NAME "meshtastic" -#define WiFi_SSID_PASSWORD "meshtastic!" \ No newline at end of file +#define WiFi_MODE 1 From 493b25f23ee31266ec35afa33bc0ba053cbd1cef Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Wed, 16 Sep 2020 20:15:00 -0700 Subject: [PATCH 07/34] Final checkin of WiFi and basic HTTP server --- src/configuration.h | 13 ------------- src/graphics/Screen.cpp | 9 +++++---- src/main.cpp | 4 ---- src/meshwifi/meshhttp.cpp | 8 ++++++-- src/meshwifi/meshwifi.cpp | 20 ++++++++++++++++++++ src/meshwifi/meshwifi.h | 1 + 6 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/configuration.h b/src/configuration.h index 63d1dbfc4..e70f1fda4 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -397,16 +397,3 @@ along with this program. If not, see . #define GPS_POWER_CTRL_CH 3 #define LORA_POWER_CTRL_CH 2 - -// ----------------------------------------------------------------------------- -// WiFi Configuration -// ----------------------------------------------------------------------------- -// -// Set WiFi credentials using the API (Does this work?) -// meshtastic --setpref WiFi_SSID_NAME yournetwork -// meshtastic --setpref WiFi_SSID_PASSWORD yourpassword -// -// WiFi_Mode -// 0 = Disabled -// 1 = Enabled -#define WiFi_MODE 1 diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index e14e4078e..29637934e 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -33,6 +33,7 @@ along with this program. If not, see . #include "mesh-pb-constants.h" #include "utils.h" #include +#include "meshwifi/meshwifi.h" using namespace meshtastic; /** @todo remove */ @@ -746,10 +747,10 @@ void Screen::setFrames() // call a method on debugInfoScreen object (for more details) normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline; -#if WiFi_MODE - // call a method on debugInfoScreen object (for more details) - normalFrames[numframes++] = &Screen::drawDebugInfoWiFiTrampoline; -#endif + if (isWifiAvailable()) { + // call a method on debugInfoScreen object (for more details) + normalFrames[numframes++] = &Screen::drawDebugInfoWiFiTrampoline; + } ui.setFrames(normalFrames, numframes); ui.enableAllIndicators(); diff --git a/src/main.cpp b/src/main.cpp index 81038030d..cc0c9a0c3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -327,10 +327,8 @@ void setup() } #endif -#if WiFi_MODE // Initialize Wifi initWifi(); -#endif if (!rIf) recordCriticalError(ErrNoRadio); @@ -423,10 +421,8 @@ void loop() // feel slow msecstosleep = 10; -#if WiFi_MODE // TODO: This should go into a thread handled by FreeRTOS. handleWebResponse(); -#endif delay(msecstosleep); } diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index b70b8fc29..f52cade57 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -3,8 +3,8 @@ #include "configuration.h" #include "main.h" #include "NodeDB.h" -#include "meshwifi.h" -#include "meshhttp.h" +#include "meshwifi/meshwifi.h" +#include "meshwifi/meshhttp.h" WebServer webserver(80); @@ -14,6 +14,10 @@ String sender = ""; void handleWebResponse() { + if (isWifiAvailable() == 0) { + return; + } + webserver.handleClient(); } diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index 19a52bf51..72d6e09f8 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -5,14 +5,34 @@ #include "NodeDB.h" #include "meshwifi/meshhttp.h" +bool isWifiAvailable() +{ + const char *wifiName = radioConfig.preferences.wifi_ssid; + const char *wifiPsw = radioConfig.preferences.wifi_password; + + if (*wifiName && *wifiPsw) { + return 1; + } else { + return 0; + } +} + +// Disable WiFi void deinitWifi() { WiFi.mode(WIFI_MODE_NULL); DEBUG_MSG("WiFi Turned Off\n"); } + +// Startup WiFi void initWifi() { + + if (isWifiAvailable() == 0) { + return; + } + //strcpy(radioConfig.preferences.wifi_ssid, WiFi_SSID_NAME); //strcpy(radioConfig.preferences.wifi_password, WiFi_SSID_PASSWORD); if (radioConfig.has_preferences) { diff --git a/src/meshwifi/meshwifi.h b/src/meshwifi/meshwifi.h index a20a114aa..2413a2a22 100644 --- a/src/meshwifi/meshwifi.h +++ b/src/meshwifi/meshwifi.h @@ -12,3 +12,4 @@ void deinitWifi(); void WiFiEvent(WiFiEvent_t event); +bool isWifiAvailable(); \ No newline at end of file From 73b47a78aa78433526f8f30e0a14add4fdf9baea Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Wed, 16 Sep 2020 22:31:07 -0700 Subject: [PATCH 08/34] Clean up and added comments about the esp32 sdk bug --- src/meshwifi/meshwifi.cpp | 82 ++++++++++++++++++------------------ src/meshwifi/meshwifi.h | 2 - src/nimble/BluetoothUtil.cpp | 4 +- 3 files changed, 42 insertions(+), 46 deletions(-) diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index 72d6e09f8..dff6ffeeb 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -20,8 +20,20 @@ bool isWifiAvailable() // Disable WiFi void deinitWifi() { + /* + Note from Jm (Sept 16, 2020): + + A bug in the ESP32 SDK was introduced in Oct 2019 that keeps the WiFi radio from + turning back on after it's shut off. See: + https://github.com/espressif/arduino-esp32/issues/3522 + + Until then, WiFi should only be allowed when there's no power + saving on the 2.4g transceiver. + */ + WiFi.mode(WIFI_MODE_NULL); DEBUG_MSG("WiFi Turned Off\n"); + WiFi.printDiag(Serial); } @@ -45,6 +57,8 @@ void initWifi() } else { WiFi.mode(WIFI_MODE_STA); WiFi.onEvent(WiFiEvent); + //esp_wifi_set_ps(WIFI_PS_NONE); // Disable power saving + DEBUG_MSG("JOINING WIFI: ssid=%s\n", wifiName); if (WiFi.begin(wifiName, wifiPsw) == WL_CONNECTED) { @@ -65,31 +79,31 @@ void WiFiEvent(WiFiEvent_t event) switch (event) { case SYSTEM_EVENT_WIFI_READY: - DEBUG_MSG("WiFi interface ready"); + DEBUG_MSG("WiFi interface ready\n"); break; case SYSTEM_EVENT_SCAN_DONE: - DEBUG_MSG("Completed scan for access points"); + DEBUG_MSG("Completed scan for access points\n"); break; case SYSTEM_EVENT_STA_START: - DEBUG_MSG("WiFi client started"); + DEBUG_MSG("WiFi client started\n"); break; case SYSTEM_EVENT_STA_STOP: - DEBUG_MSG("WiFi clients stopped"); + DEBUG_MSG("WiFi clients stopped\n"); break; case SYSTEM_EVENT_STA_CONNECTED: - DEBUG_MSG("Connected to access point"); + DEBUG_MSG("Connected to access point\n"); break; case SYSTEM_EVENT_STA_DISCONNECTED: - DEBUG_MSG("Disconnected from WiFi access point"); + DEBUG_MSG("Disconnected from WiFi access point\n"); // Reconnect WiFi reconnectWiFi(); break; case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: - DEBUG_MSG("Authentication mode of access point has changed"); + DEBUG_MSG("Authentication mode of access point has changed\n"); break; case SYSTEM_EVENT_STA_GOT_IP: - DEBUG_MSG("Obtained IP address: "); + DEBUG_MSG("Obtained IP address: \n"); Serial.println(WiFi.localIP()); // Start web server @@ -97,72 +111,56 @@ void WiFiEvent(WiFiEvent_t event) break; case SYSTEM_EVENT_STA_LOST_IP: - DEBUG_MSG("Lost IP address and IP address is reset to 0"); + DEBUG_MSG("Lost IP address and IP address is reset to 0\n"); break; case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: - DEBUG_MSG("WiFi Protected Setup (WPS): succeeded in enrollee mode"); + DEBUG_MSG("WiFi Protected Setup (WPS): succeeded in enrollee mode\n"); break; case SYSTEM_EVENT_STA_WPS_ER_FAILED: - DEBUG_MSG("WiFi Protected Setup (WPS): failed in enrollee mode"); + DEBUG_MSG("WiFi Protected Setup (WPS): failed in enrollee mode\n"); break; case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: - DEBUG_MSG("WiFi Protected Setup (WPS): timeout in enrollee mode"); + DEBUG_MSG("WiFi Protected Setup (WPS): timeout in enrollee mode\n"); break; case SYSTEM_EVENT_STA_WPS_ER_PIN: - DEBUG_MSG("WiFi Protected Setup (WPS): pin code in enrollee mode"); + DEBUG_MSG("WiFi Protected Setup (WPS): pin code in enrollee mode\n"); break; case SYSTEM_EVENT_AP_START: - DEBUG_MSG("WiFi access point started"); + DEBUG_MSG("WiFi access point started\n"); break; case SYSTEM_EVENT_AP_STOP: - DEBUG_MSG("WiFi access point stopped"); + DEBUG_MSG("WiFi access point stopped\n"); break; case SYSTEM_EVENT_AP_STACONNECTED: - DEBUG_MSG("Client connected"); + DEBUG_MSG("Client connected\n"); break; case SYSTEM_EVENT_AP_STADISCONNECTED: - DEBUG_MSG("Client disconnected"); + DEBUG_MSG("Client disconnected\n"); break; case SYSTEM_EVENT_AP_STAIPASSIGNED: - DEBUG_MSG("Assigned IP address to client"); + DEBUG_MSG("Assigned IP address to client\n"); break; case SYSTEM_EVENT_AP_PROBEREQRECVED: - DEBUG_MSG("Received probe request"); + DEBUG_MSG("Received probe request\n"); break; case SYSTEM_EVENT_GOT_IP6: - DEBUG_MSG("IPv6 is preferred"); + DEBUG_MSG("IPv6 is preferred\n"); break; case SYSTEM_EVENT_ETH_START: - DEBUG_MSG("Ethernet started"); + DEBUG_MSG("Ethernet started\n"); break; case SYSTEM_EVENT_ETH_STOP: - DEBUG_MSG("Ethernet stopped"); + DEBUG_MSG("Ethernet stopped\n"); break; case SYSTEM_EVENT_ETH_CONNECTED: - DEBUG_MSG("Ethernet connected"); + DEBUG_MSG("Ethernet connected\n"); break; case SYSTEM_EVENT_ETH_DISCONNECTED: - DEBUG_MSG("Ethernet disconnected"); + DEBUG_MSG("Ethernet disconnected\n"); break; case SYSTEM_EVENT_ETH_GOT_IP: - DEBUG_MSG("Obtained IP address"); + DEBUG_MSG("Obtained IP address\n"); break; default: break; } -} - -void reconnectWiFi() { - const char *wifiName = radioConfig.preferences.wifi_ssid; - const char *wifiPsw = radioConfig.preferences.wifi_password; - - if (radioConfig.has_preferences) { - - if (*wifiName) { - - DEBUG_MSG("... Reconnecting to WiFi access point"); - - WiFi.mode(WIFI_MODE_STA); - WiFi.begin(wifiName, wifiPsw); - } - } -} +} \ No newline at end of file diff --git a/src/meshwifi/meshwifi.h b/src/meshwifi/meshwifi.h index 2413a2a22..044839ab6 100644 --- a/src/meshwifi/meshwifi.h +++ b/src/meshwifi/meshwifi.h @@ -4,8 +4,6 @@ #include #include -void reconnectWiFi(); - void initWifi(); void deinitWifi(); diff --git a/src/nimble/BluetoothUtil.cpp b/src/nimble/BluetoothUtil.cpp index 00e7deea1..a78b0098f 100644 --- a/src/nimble/BluetoothUtil.cpp +++ b/src/nimble/BluetoothUtil.cpp @@ -523,12 +523,12 @@ void setBluetoothEnable(bool on) if (firstTime) { firstTime = 0; } else { - reconnectWiFi(); + initWifi(); } } else { // We have to totally teardown our bluetooth objects to prevent leaks - deinitBLE(); deinitWifi(); // shutdown wifi + deinitBLE(); Serial.printf("Shutdown BT: %u heap size\n", ESP.getFreeHeap()); // ESP_ERROR_CHECK( heap_trace_stop() ); From 64710a6a04f60130da18e7da5e00a14c19789836 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Wed, 16 Sep 2020 23:16:11 -0700 Subject: [PATCH 09/34] renamed reconnectWiFi to initWifi --- src/meshwifi/meshwifi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index dff6ffeeb..14ac8a2a7 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -97,7 +97,7 @@ void WiFiEvent(WiFiEvent_t event) DEBUG_MSG("Disconnected from WiFi access point\n"); // Reconnect WiFi - reconnectWiFi(); + initWifi(); break; case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: DEBUG_MSG("Authentication mode of access point has changed\n"); From 6e5e5822aa438d3a046077bafd7c26c34de87ebd Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 18 Sep 2020 10:48:39 -0700 Subject: [PATCH 10/34] Make wifi optional and exclude from nrf52 builds --- platformio.ini | 2 +- src/configuration.h | 2 + src/graphics/Screen.cpp | 3 +- src/graphics/Screen.h | 1 - src/meshwifi/meshhttp.h | 1 - src/meshwifi/meshwifi.cpp | 191 +++++++++++++++++++------------------- src/meshwifi/meshwifi.h | 6 +- src/nrf52/wifi-nrf52.cpp | 13 +++ 8 files changed, 117 insertions(+), 102 deletions(-) create mode 100644 src/nrf52/wifi-nrf52.cpp diff --git a/platformio.ini b/platformio.ini index 1069f8e03..0ba38adc7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -160,7 +160,7 @@ build_flags = -Isdk-nrfxlib/crypto/nrf_oberon/include -Lsdk-nrfxlib/crypto/nrf_oberon/lib/cortex-m4/hard-float/ -lliboberon_3.0.3 ;-DCFG_DEBUG=3 src_filter = - ${env.src_filter} - - + ${env.src_filter} - - - lib_ignore = BluetoothOTA monitor_port = /dev/ttyACM1 diff --git a/src/configuration.h b/src/configuration.h index e70f1fda4..b9c869102 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -101,6 +101,8 @@ along with this program. If not, see . // Standard definitions for ESP32 targets // +#define HAS_WIFI + #define GPS_SERIAL_NUM 1 #define GPS_RX_PIN 34 #ifdef USE_JTAG diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 29637934e..6675d8a1f 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -32,7 +32,6 @@ along with this program. If not, see . #include "main.h" #include "mesh-pb-constants.h" #include "utils.h" -#include #include "meshwifi/meshwifi.h" using namespace meshtastic; /** @todo remove */ @@ -842,6 +841,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 // Jm void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { +#ifdef HAS_WIFI const char *wifiName = radioConfig.preferences.wifi_ssid; const char *wifiPsw = radioConfig.preferences.wifi_password; @@ -869,6 +869,7 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i display->setPixel(0, 0); heartbeat = !heartbeat; #endif +#endif } diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index 8f5a6de2a..0fc6e5880 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -17,7 +17,6 @@ #include "concurrency/PeriodicTask.h" #include "power.h" #include -#include namespace graphics { diff --git a/src/meshwifi/meshhttp.h b/src/meshwifi/meshhttp.h index cbff51db7..cabb1a2c3 100644 --- a/src/meshwifi/meshhttp.h +++ b/src/meshwifi/meshhttp.h @@ -2,7 +2,6 @@ #include #include -#include void initWebServer(); diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index 14ac8a2a7..8c1d2c8f6 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -1,11 +1,13 @@ #include "meshwifi.h" -#include +#include "NodeDB.h" #include "configuration.h" #include "main.h" -#include "NodeDB.h" #include "meshwifi/meshhttp.h" +#include -bool isWifiAvailable() +static void WiFiEvent(WiFiEvent_t event); + +bool isWifiAvailable() { const char *wifiName = radioConfig.preferences.wifi_ssid; const char *wifiPsw = radioConfig.preferences.wifi_password; @@ -20,33 +22,31 @@ bool isWifiAvailable() // Disable WiFi void deinitWifi() { - /* + /* Note from Jm (Sept 16, 2020): - + A bug in the ESP32 SDK was introduced in Oct 2019 that keeps the WiFi radio from turning back on after it's shut off. See: https://github.com/espressif/arduino-esp32/issues/3522 Until then, WiFi should only be allowed when there's no power saving on the 2.4g transceiver. - */ + */ WiFi.mode(WIFI_MODE_NULL); DEBUG_MSG("WiFi Turned Off\n"); WiFi.printDiag(Serial); } - // Startup WiFi void initWifi() { - if (isWifiAvailable() == 0) { return; } - //strcpy(radioConfig.preferences.wifi_ssid, WiFi_SSID_NAME); - //strcpy(radioConfig.preferences.wifi_password, WiFi_SSID_PASSWORD); + // strcpy(radioConfig.preferences.wifi_ssid, WiFi_SSID_NAME); + // strcpy(radioConfig.preferences.wifi_password, WiFi_SSID_PASSWORD); if (radioConfig.has_preferences) { const char *wifiName = radioConfig.preferences.wifi_ssid; @@ -57,8 +57,7 @@ void initWifi() } else { WiFi.mode(WIFI_MODE_STA); WiFi.onEvent(WiFiEvent); - //esp_wifi_set_ps(WIFI_PS_NONE); // Disable power saving - + // esp_wifi_set_ps(WIFI_PS_NONE); // Disable power saving DEBUG_MSG("JOINING WIFI: ssid=%s\n", wifiName); if (WiFi.begin(wifiName, wifiPsw) == WL_CONNECTED) { @@ -72,95 +71,95 @@ void initWifi() DEBUG_MSG("Not using WIFI\n"); } - -void WiFiEvent(WiFiEvent_t event) +static void WiFiEvent(WiFiEvent_t event) { DEBUG_MSG("************ [WiFi-event] event: %d ************\n", event); switch (event) { - case SYSTEM_EVENT_WIFI_READY: - DEBUG_MSG("WiFi interface ready\n"); - break; - case SYSTEM_EVENT_SCAN_DONE: - DEBUG_MSG("Completed scan for access points\n"); - break; - case SYSTEM_EVENT_STA_START: - DEBUG_MSG("WiFi client started\n"); - break; - case SYSTEM_EVENT_STA_STOP: - DEBUG_MSG("WiFi clients stopped\n"); - break; - case SYSTEM_EVENT_STA_CONNECTED: - DEBUG_MSG("Connected to access point\n"); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - DEBUG_MSG("Disconnected from WiFi access point\n"); + case SYSTEM_EVENT_WIFI_READY: + DEBUG_MSG("WiFi interface ready\n"); + break; + case SYSTEM_EVENT_SCAN_DONE: + DEBUG_MSG("Completed scan for access points\n"); + break; + case SYSTEM_EVENT_STA_START: + DEBUG_MSG("WiFi client started\n"); + break; + case SYSTEM_EVENT_STA_STOP: + DEBUG_MSG("WiFi clients stopped\n"); + break; + case SYSTEM_EVENT_STA_CONNECTED: + DEBUG_MSG("Connected to access point\n"); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + DEBUG_MSG("Disconnected from WiFi access point\n"); - // Reconnect WiFi - initWifi(); - break; - case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: - DEBUG_MSG("Authentication mode of access point has changed\n"); - break; - case SYSTEM_EVENT_STA_GOT_IP: - DEBUG_MSG("Obtained IP address: \n"); - Serial.println(WiFi.localIP()); + // Reconnect WiFi + initWifi(); + break; + case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: + DEBUG_MSG("Authentication mode of access point has changed\n"); + break; + case SYSTEM_EVENT_STA_GOT_IP: + DEBUG_MSG("Obtained IP address: \n"); + Serial.println(WiFi.localIP()); - // Start web server - initWebServer(); - - break; - case SYSTEM_EVENT_STA_LOST_IP: - DEBUG_MSG("Lost IP address and IP address is reset to 0\n"); - break; - case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: - DEBUG_MSG("WiFi Protected Setup (WPS): succeeded in enrollee mode\n"); - break; - case SYSTEM_EVENT_STA_WPS_ER_FAILED: - DEBUG_MSG("WiFi Protected Setup (WPS): failed in enrollee mode\n"); - break; - case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: - DEBUG_MSG("WiFi Protected Setup (WPS): timeout in enrollee mode\n"); - break; - case SYSTEM_EVENT_STA_WPS_ER_PIN: - DEBUG_MSG("WiFi Protected Setup (WPS): pin code in enrollee mode\n"); - break; - case SYSTEM_EVENT_AP_START: - DEBUG_MSG("WiFi access point started\n"); - break; - case SYSTEM_EVENT_AP_STOP: - DEBUG_MSG("WiFi access point stopped\n"); - break; - case SYSTEM_EVENT_AP_STACONNECTED: - DEBUG_MSG("Client connected\n"); - break; - case SYSTEM_EVENT_AP_STADISCONNECTED: - DEBUG_MSG("Client disconnected\n"); - break; - case SYSTEM_EVENT_AP_STAIPASSIGNED: - DEBUG_MSG("Assigned IP address to client\n"); - break; - case SYSTEM_EVENT_AP_PROBEREQRECVED: - DEBUG_MSG("Received probe request\n"); - break; - case SYSTEM_EVENT_GOT_IP6: - DEBUG_MSG("IPv6 is preferred\n"); - break; - case SYSTEM_EVENT_ETH_START: - DEBUG_MSG("Ethernet started\n"); - break; - case SYSTEM_EVENT_ETH_STOP: - DEBUG_MSG("Ethernet stopped\n"); - break; - case SYSTEM_EVENT_ETH_CONNECTED: - DEBUG_MSG("Ethernet connected\n"); - break; - case SYSTEM_EVENT_ETH_DISCONNECTED: - DEBUG_MSG("Ethernet disconnected\n"); - break; - case SYSTEM_EVENT_ETH_GOT_IP: - DEBUG_MSG("Obtained IP address\n"); - break; - default: break; + // Start web server + initWebServer(); + + break; + case SYSTEM_EVENT_STA_LOST_IP: + DEBUG_MSG("Lost IP address and IP address is reset to 0\n"); + break; + case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: + DEBUG_MSG("WiFi Protected Setup (WPS): succeeded in enrollee mode\n"); + break; + case SYSTEM_EVENT_STA_WPS_ER_FAILED: + DEBUG_MSG("WiFi Protected Setup (WPS): failed in enrollee mode\n"); + break; + case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: + DEBUG_MSG("WiFi Protected Setup (WPS): timeout in enrollee mode\n"); + break; + case SYSTEM_EVENT_STA_WPS_ER_PIN: + DEBUG_MSG("WiFi Protected Setup (WPS): pin code in enrollee mode\n"); + break; + case SYSTEM_EVENT_AP_START: + DEBUG_MSG("WiFi access point started\n"); + break; + case SYSTEM_EVENT_AP_STOP: + DEBUG_MSG("WiFi access point stopped\n"); + break; + case SYSTEM_EVENT_AP_STACONNECTED: + DEBUG_MSG("Client connected\n"); + break; + case SYSTEM_EVENT_AP_STADISCONNECTED: + DEBUG_MSG("Client disconnected\n"); + break; + case SYSTEM_EVENT_AP_STAIPASSIGNED: + DEBUG_MSG("Assigned IP address to client\n"); + break; + case SYSTEM_EVENT_AP_PROBEREQRECVED: + DEBUG_MSG("Received probe request\n"); + break; + case SYSTEM_EVENT_GOT_IP6: + DEBUG_MSG("IPv6 is preferred\n"); + break; + case SYSTEM_EVENT_ETH_START: + DEBUG_MSG("Ethernet started\n"); + break; + case SYSTEM_EVENT_ETH_STOP: + DEBUG_MSG("Ethernet stopped\n"); + break; + case SYSTEM_EVENT_ETH_CONNECTED: + DEBUG_MSG("Ethernet connected\n"); + break; + case SYSTEM_EVENT_ETH_DISCONNECTED: + DEBUG_MSG("Ethernet disconnected\n"); + break; + case SYSTEM_EVENT_ETH_GOT_IP: + DEBUG_MSG("Obtained IP address\n"); + break; + default: + break; } } \ No newline at end of file diff --git a/src/meshwifi/meshwifi.h b/src/meshwifi/meshwifi.h index 044839ab6..9f018de0d 100644 --- a/src/meshwifi/meshwifi.h +++ b/src/meshwifi/meshwifi.h @@ -1,13 +1,15 @@ #pragma once +#include "configuration.h" #include #include + +#ifdef HAS_WIFI #include +#endif void initWifi(); void deinitWifi(); -void WiFiEvent(WiFiEvent_t event); - bool isWifiAvailable(); \ No newline at end of file diff --git a/src/nrf52/wifi-nrf52.cpp b/src/nrf52/wifi-nrf52.cpp new file mode 100644 index 000000000..e4885add7 --- /dev/null +++ b/src/nrf52/wifi-nrf52.cpp @@ -0,0 +1,13 @@ +#include "meshwifi/meshhttp.h" +#include "meshwifi/meshwifi.h" + +void initWifi() {} + +void deinitWifi() {} + +bool isWifiAvailable() +{ + return false; +} + +void handleWebResponse() {} \ No newline at end of file From b203c95dd1062a3913d22e0caafbc525c5173670 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Fri, 18 Sep 2020 15:33:03 -0700 Subject: [PATCH 11/34] changes for soft ap + captive portal --- src/graphics/Screen.cpp | 14 ++++++++---- src/main.cpp | 1 + src/meshwifi/meshhttp.cpp | 14 +++++++++++- src/meshwifi/meshhttp.h | 1 + src/meshwifi/meshwifi.cpp | 42 +++++++++++++++++++++++++++++++----- src/meshwifi/meshwifi.h | 5 ++++- src/nimble/BluetoothUtil.cpp | 4 +++- 7 files changed, 69 insertions(+), 12 deletions(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 29637934e..1acffc4d7 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -852,16 +852,22 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i // The coordinates define the left starting point of the text display->setTextAlignment(TEXT_ALIGN_LEFT); - if ( WiFi.status() != WL_CONNECTED ) { + if (radioConfig.preferences.wifi_ap_mode) { + display->drawString(x, y, String("WiFi - Software AP")); + } else if ( WiFi.status() != WL_CONNECTED ) { display->drawString(x, y, String("WiFi - Not Connected")); } else { display->drawString(x, y, String("WiFi - Connected")); } - display->drawString(x, y + FONT_HEIGHT * 1, WiFi.localIP().toString().c_str()); + if (radioConfig.preferences.wifi_ap_mode) { + display->drawString(x, y + FONT_HEIGHT * 1, "IP " + String(WiFi.softAPIP().toString().c_str())); + } else { + display->drawString(x, y + FONT_HEIGHT * 1, "IP " + String(WiFi.localIP().toString().c_str())); + } - display->drawString(x, y + FONT_HEIGHT * 2, wifiName); - display->drawString(x, y + FONT_HEIGHT * 3, wifiPsw); + display->drawString(x, y + FONT_HEIGHT * 2, "SSID " + String(wifiName)); + display->drawString(x, y + FONT_HEIGHT * 3, "PWD " + String(wifiPsw)); /* Display a heartbeat pixel that blinks every time the frame is redrawn */ #ifdef SHOW_REDRAWS diff --git a/src/main.cpp b/src/main.cpp index b0d133f22..65881b9e1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -423,6 +423,7 @@ void loop() // TODO: This should go into a thread handled by FreeRTOS. handleWebResponse(); + handleDNSResponse(); delay(msecstosleep); } diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index f52cade57..09219602e 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -25,6 +25,7 @@ void initWebServer() { webserver.onNotFound(handleNotFound); //webserver.on("/", handleJSONChatHistory); //webserver.on("/json/chat/history", handleJSONChatHistory); + webserver.on("/hotspot-detect.html", handleHotspot); webserver.on("/", []() { webserver.send(200, "text/plain", "Everything is awesome!"); }); @@ -69,13 +70,24 @@ void handleNotFound() { 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); /* */ } +/* + This supports the Apple Captive Network Assistant (CNA) Portal +*/ +void handleHotspot() { + DEBUG_MSG("Hotspot Request\n"); + String out = ""; + //out += "Success\n"; + out += "\n"; + webserver.send ( 200, "text/html", out ); + return; +} void notifyWebUI() { DEBUG_MSG("************ Got a message! ************\n"); diff --git a/src/meshwifi/meshhttp.h b/src/meshwifi/meshhttp.h index cbff51db7..04d1db0fc 100644 --- a/src/meshwifi/meshhttp.h +++ b/src/meshwifi/meshhttp.h @@ -14,3 +14,4 @@ void handleJSONChatHistory(); void notifyWebUI(); +void handleHotspot(); diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index 14ac8a2a7..3ff8ed122 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -1,10 +1,13 @@ #include "meshwifi.h" #include +#include #include "configuration.h" #include "main.h" #include "NodeDB.h" #include "meshwifi/meshhttp.h" +DNSServer dnsServer; + bool isWifiAvailable() { const char *wifiName = radioConfig.preferences.wifi_ssid; @@ -45,21 +48,39 @@ void initWifi() return; } - //strcpy(radioConfig.preferences.wifi_ssid, WiFi_SSID_NAME); - //strcpy(radioConfig.preferences.wifi_password, WiFi_SSID_PASSWORD); if (radioConfig.has_preferences) { const char *wifiName = radioConfig.preferences.wifi_ssid; + const char *wifiPsw = radioConfig.preferences.wifi_password; - if (*wifiName) { - const char *wifiPsw = radioConfig.preferences.wifi_password; + if (1) { + radioConfig.preferences.wifi_ap_mode = 1; + strcpy(radioConfig.preferences.wifi_ssid, "MeshTest2"); + strcpy(radioConfig.preferences.wifi_password, "12345678"); + } else { + radioConfig.preferences.wifi_ap_mode = 0; + strcpy(radioConfig.preferences.wifi_ssid, "meshtastic"); + strcpy(radioConfig.preferences.wifi_password, "meshtastic!"); + } + + + if (*wifiName && *wifiPsw) { if (radioConfig.preferences.wifi_ap_mode) { + + 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", wifiName, WiFi.softAP(wifiName, wifiPsw)); + DEBUG_MSG("MY IP ADDRESS: %s\n", WiFi.softAPIP().toString().c_str()); + + dnsServer.start(53, "*", apIP); + + } else { WiFi.mode(WIFI_MODE_STA); WiFi.onEvent(WiFiEvent); //esp_wifi_set_ps(WIFI_PS_NONE); // Disable power saving - DEBUG_MSG("JOINING WIFI: ssid=%s\n", wifiName); if (WiFi.begin(wifiName, wifiPsw) == WL_CONNECTED) { DEBUG_MSG("MY IP ADDRESS: %s\n", WiFi.localIP().toString().c_str()); @@ -127,6 +148,11 @@ void WiFiEvent(WiFiEvent_t event) break; case SYSTEM_EVENT_AP_START: DEBUG_MSG("WiFi access point started\n"); + Serial.println(WiFi.softAPIP()); + + // Start web server + initWebServer(); + break; case SYSTEM_EVENT_AP_STOP: DEBUG_MSG("WiFi access point stopped\n"); @@ -163,4 +189,10 @@ void WiFiEvent(WiFiEvent_t event) break; default: break; } +} + +void handleDNSResponse() { + if (radioConfig.preferences.wifi_ap_mode) { + dnsServer.processNextRequest(); + } } \ No newline at end of file diff --git a/src/meshwifi/meshwifi.h b/src/meshwifi/meshwifi.h index 044839ab6..970cc4478 100644 --- a/src/meshwifi/meshwifi.h +++ b/src/meshwifi/meshwifi.h @@ -3,6 +3,7 @@ #include #include #include +#include void initWifi(); @@ -10,4 +11,6 @@ void deinitWifi(); void WiFiEvent(WiFiEvent_t event); -bool isWifiAvailable(); \ No newline at end of file +bool isWifiAvailable(); + +void handleDNSResponse(); diff --git a/src/nimble/BluetoothUtil.cpp b/src/nimble/BluetoothUtil.cpp index a78b0098f..de9f0c611 100644 --- a/src/nimble/BluetoothUtil.cpp +++ b/src/nimble/BluetoothUtil.cpp @@ -526,8 +526,10 @@ void setBluetoothEnable(bool on) initWifi(); } } else { + // shutdown wifi + deinitWifi(); + // We have to totally teardown our bluetooth objects to prevent leaks - deinitWifi(); // shutdown wifi deinitBLE(); Serial.printf("Shutdown BT: %u heap size\n", ESP.getFreeHeap()); From 4d72afebe6aed06711fb83496f58d0769367fbc3 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Fri, 18 Sep 2020 18:16:58 -0700 Subject: [PATCH 12/34] Soft AP and basic captive portal done. --- src/meshwifi/meshwifi.cpp | 3 ++- src/meshwifi/meshwifi.h | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index 3e8af00df..f395ff7b0 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -52,6 +52,7 @@ void initWifi() const char *wifiName = radioConfig.preferences.wifi_ssid; const char *wifiPsw = radioConfig.preferences.wifi_password; + /* if (1) { radioConfig.preferences.wifi_ap_mode = 1; strcpy(radioConfig.preferences.wifi_ssid, "MeshTest2"); @@ -61,7 +62,7 @@ void initWifi() strcpy(radioConfig.preferences.wifi_ssid, "meshtastic"); strcpy(radioConfig.preferences.wifi_password, "meshtastic!"); } - + */ if (*wifiName && *wifiPsw) { if (radioConfig.preferences.wifi_ap_mode) { diff --git a/src/meshwifi/meshwifi.h b/src/meshwifi/meshwifi.h index facff0a1d..44fff707f 100644 --- a/src/meshwifi/meshwifi.h +++ b/src/meshwifi/meshwifi.h @@ -13,6 +13,4 @@ void initWifi(); void deinitWifi(); bool isWifiAvailable(); -void WiFiEvent(WiFiEvent_t event); - void handleDNSResponse(); From 65fc1cf4a6419ee6a28a2161f8dee47256f651d8 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Fri, 18 Sep 2020 18:29:16 -0700 Subject: [PATCH 13/34] Moved handleDNSResponse into handleWebResponse and used the autoformatter --- src/main.cpp | 1 - src/meshwifi/meshhttp.cpp | 57 +++++++++++++++++++-------------------- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 65881b9e1..b0d133f22 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -423,7 +423,6 @@ void loop() // TODO: This should go into a thread handled by FreeRTOS. handleWebResponse(); - handleDNSResponse(); delay(msecstosleep); } diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index 09219602e..c2f6ed342 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -1,40 +1,41 @@ -#include -#include +#include "meshwifi/meshhttp.h" +#include "NodeDB.h" #include "configuration.h" #include "main.h" -#include "NodeDB.h" #include "meshwifi/meshwifi.h" -#include "meshwifi/meshhttp.h" - +#include +#include WebServer webserver(80); String something = ""; String sender = ""; - -void handleWebResponse() { +void handleWebResponse() +{ if (isWifiAvailable() == 0) { return; } + // We're going to handle the DNS responder here so it + // will be ignored by the NRF boards. + handleDNSResponse(); + webserver.handleClient(); } -void initWebServer() { +void initWebServer() +{ webserver.onNotFound(handleNotFound); - //webserver.on("/", handleJSONChatHistory); - //webserver.on("/json/chat/history", handleJSONChatHistory); + // webserver.on("/", handleJSONChatHistory); + // webserver.on("/json/chat/history", handleJSONChatHistory); webserver.on("/hotspot-detect.html", handleHotspot); - webserver.on("/", []() { - webserver.send(200, "text/plain", "Everything is awesome!"); - }); + webserver.on("/", []() { webserver.send(200, "text/plain", "Everything is awesome!"); }); webserver.begin(); - } - -void handleJSONChatHistory() { +void handleJSONChatHistory() +{ String out = ""; out += "{\n"; @@ -46,18 +47,16 @@ void handleJSONChatHistory() { out += "\"" + something + "\""; out += "]\n"; - - out += "\n"; out += " }\n"; out += "}\n"; - webserver.send ( 200, "application/json", out ); + webserver.send(200, "application/json", out); return; - } -void handleNotFound() { +void handleNotFound() +{ String message = "File Not Found\n\n"; message += "URI: "; message += webserver.uri(); @@ -73,33 +72,33 @@ void handleNotFound() { Serial.println(message); webserver.send(404, "text/plain", message); /* - */ + */ } /* This supports the Apple Captive Network Assistant (CNA) Portal */ -void handleHotspot() { +void handleHotspot() +{ DEBUG_MSG("Hotspot Request\n"); String out = ""; - //out += "Success\n"; + // out += "Success\n"; out += "\n"; - webserver.send ( 200, "text/html", out ); + webserver.send(200, "text/html", out); return; } -void notifyWebUI() { +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; - } \ No newline at end of file From 82fbedbf4155fcf27b84818292ca80fca1a63a4a Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Fri, 18 Sep 2020 18:51:42 -0700 Subject: [PATCH 14/34] Auto formatting of meshwifi.cpp --- src/meshwifi/meshwifi.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index f395ff7b0..a88ed6ae3 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -3,14 +3,14 @@ #include "configuration.h" #include "main.h" #include "meshwifi/meshhttp.h" -#include #include +#include static void WiFiEvent(WiFiEvent_t event); DNSServer dnsServer; -bool isWifiAvailable() +bool isWifiAvailable() { const char *wifiName = radioConfig.preferences.wifi_ssid; const char *wifiPsw = radioConfig.preferences.wifi_password; @@ -66,7 +66,7 @@ void initWifi() if (*wifiName && *wifiPsw) { if (radioConfig.preferences.wifi_ap_mode) { - + IPAddress apIP(192, 168, 42, 1); WiFi.onEvent(WiFiEvent); @@ -76,7 +76,6 @@ void initWifi() dnsServer.start(53, "*", apIP); - } else { WiFi.mode(WIFI_MODE_STA); WiFi.onEvent(WiFiEvent); @@ -189,11 +188,11 @@ static void WiFiEvent(WiFiEvent_t event) break; default: break; - } } -void handleDNSResponse() { +void handleDNSResponse() +{ if (radioConfig.preferences.wifi_ap_mode) { dnsServer.processNextRequest(); } From 6e3b22c624db852ca8e76e142e57e16c2991c82c Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Fri, 18 Sep 2020 20:42:35 -0700 Subject: [PATCH 15/34] Stub for a handler of the root (/) of the web server with a html table and form for chat --- src/meshwifi/meshhttp.cpp | 62 ++++++++++++++++++++++++++++++++++++++- src/meshwifi/meshhttp.h | 2 ++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index c2f6ed342..0f8988ddf 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -30,7 +30,7 @@ void initWebServer() // webserver.on("/", handleJSONChatHistory); // webserver.on("/json/chat/history", handleJSONChatHistory); webserver.on("/hotspot-detect.html", handleHotspot); - webserver.on("/", []() { webserver.send(200, "text/plain", "Everything is awesome!"); }); + webserver.on("/", handleRoot); webserver.begin(); } @@ -82,6 +82,11 @@ void handleHotspot() { DEBUG_MSG("Hotspot Request\n"); + /* + If we don't do a redirect, be sure to return a "Success" message + otherwise iOS will have trouble detecting that the connection to the SoftAP worked. + */ + String out = ""; // out += "Success\n"; out += "\n"; @@ -89,6 +94,61 @@ void handleHotspot() return; } +void handleRoot() +{ + DEBUG_MSG("Hotspot Request\n"); + + /* + If we don't do a redirect, be sure to return a "Success" message + otherwise iOS will have trouble detecting that the connection to the SoftAP worked. + */ + + String out = ""; + // out += "Success\n"; + out += "\n" + "\n" + "\n" + "\n" + "Meshtastic - WebUI\n" + "\n" + "\n" + "\n" + "
\n" + "
\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
Meshtastic - WebUI (Pre-Alpha)
\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
Channels:
\n" + "
\n" + " #general
\n" + " #stuff
\n" + " #things
\n" + "
Everything is awesome!
\n" + "
\n" + "
\n" + "
\n" + "\n" + "\n"; + webserver.send(200, "text/html", out); + return; +} + void notifyWebUI() { DEBUG_MSG("************ Got a message! ************\n"); diff --git a/src/meshwifi/meshhttp.h b/src/meshwifi/meshhttp.h index 8c607f6fd..b1a5dbb94 100644 --- a/src/meshwifi/meshhttp.h +++ b/src/meshwifi/meshhttp.h @@ -14,3 +14,5 @@ void handleJSONChatHistory(); void notifyWebUI(); void handleHotspot(); + +void handleRoot(); \ No newline at end of file From 3c0429deee844421a6f7a783613520a9d76691c3 Mon Sep 17 00:00:00 2001 From: geeksville Date: Sat, 19 Sep 2020 11:19:42 -0700 Subject: [PATCH 16/34] Add new factory_reset preferences option clients can set --- proto | 2 +- src/mesh/MeshService.cpp | 6 ++++-- src/mesh/MeshService.h | 6 ++++-- src/mesh/NodeDB.cpp | 23 ++++++++++++++++++----- src/mesh/NodeDB.h | 9 +++++++-- src/mesh/PhoneAPI.cpp | 5 ++++- src/mesh/mesh.pb.c | 2 +- src/mesh/mesh.pb.h | 20 +++++++++++++------- 8 files changed, 52 insertions(+), 21 deletions(-) diff --git a/proto b/proto index ce422b7c4..4e431c841 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit ce422b7c448906c6fee3eef64bbd41adfbc990f0 +Subproject commit 4e431c841015edfdde925acf5ee4ac0a2272edff diff --git a/src/mesh/MeshService.cpp b/src/mesh/MeshService.cpp index 3356e0922..8baed24c1 100644 --- a/src/mesh/MeshService.cpp +++ b/src/mesh/MeshService.cpp @@ -197,12 +197,14 @@ void MeshService::loop() } /// The radioConfig object just changed, call this to force the hw to change to the new settings -void MeshService::reloadConfig() +bool MeshService::reloadConfig() { // If we can successfully set this radio to these settings, save them to disk - nodeDB.resetRadioConfig(); // Don't let the phone send us fatally bad settings + bool didReset = nodeDB.resetRadioConfig(); // Don't let the phone send us fatally bad settings configChanged.notifyObservers(NULL); nodeDB.saveToDisk(); + + return didReset; } /// The owner User record just got updated, update our node DB and broadcast the info into the mesh diff --git a/src/mesh/MeshService.h b/src/mesh/MeshService.h index a12f087b3..a30f3d4ec 100644 --- a/src/mesh/MeshService.h +++ b/src/mesh/MeshService.h @@ -63,8 +63,10 @@ class MeshService */ void handleToRadio(MeshPacket &p); - /// The radioConfig object just changed, call this to force the hw to change to the new settings - void reloadConfig(); + /** The radioConfig object just changed, call this to force the hw to change to the new settings + * @return true if client devices should be sent a new set of radio configs + */ + bool reloadConfig(); /// The owner User record just got updated, update our node DB and broadcast the info into the mesh void reloadOwner(); diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 634bd9515..0bed24004 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -102,14 +102,23 @@ const char *getChannelName() NodeDB::NodeDB() : nodes(devicestate.node_db), numNodes(&devicestate.node_db_count) {} -void NodeDB::resetRadioConfig() +bool NodeDB::resetRadioConfig() { + bool didFactoryReset = false; + /// 16 bytes of random PSK for our _public_ default channel that all devices power up on (AES128) static const uint8_t defaultpsk[] = {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59, 0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0xbf}; - if (radioConfig.preferences.sds_secs == 0) { - DEBUG_MSG("RadioConfig reset!\n"); + if (radioConfig.preferences.factory_reset) { + DEBUG_MSG("Performing factory reset!\n"); + installDefaultDeviceState(); + didFactoryReset = true; + } else if (radioConfig.preferences.sds_secs == 0) { + DEBUG_MSG("Fixing bogus RadioConfig!\n"); + + radioConfig.preferences.factory_reset = false; // never save this to disk + radioConfig.preferences.send_owner_interval = 4; // per sw-design.md radioConfig.preferences.position_broadcast_secs = 15 * 60; radioConfig.preferences.wait_bluetooth_secs = 120; @@ -123,8 +132,8 @@ void NodeDB::resetRadioConfig() radioConfig.has_preferences = true; // radioConfig.modem_config = RadioConfig_ModemConfig_Bw125Cr45Sf128; // medium range and fast - // channelSettings.modem_config = ChannelSettings_ModemConfig_Bw500Cr45Sf128; // short range and fast, but wide bandwidth - // so incompatible radios can talk together + // channelSettings.modem_config = ChannelSettings_ModemConfig_Bw500Cr45Sf128; // short range and fast, but wide + // bandwidth so incompatible radios can talk together channelSettings.modem_config = ChannelSettings_ModemConfig_Bw125Cr48Sf4096; // slow and long range channelSettings.tx_power = 0; // default @@ -147,12 +156,16 @@ void NodeDB::resetRadioConfig() radioConfig.preferences.position_broadcast_secs = 6 * 60; radioConfig.preferences.ls_secs = 60; } + + return didFactoryReset; } void NodeDB::installDefaultDeviceState() { memset(&devicestate, 0, sizeof(devicestate)); + *numNodes = 0; // Forget node DB + // init our devicestate with valid flags so protobuf writing/reading will work devicestate.has_my_node = true; devicestate.has_radio = true; diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index bd22f730f..e1a1b77d6 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -46,8 +46,13 @@ class NodeDB /// write to flash void saveToDisk(); - // Reinit radio config if needed, because sometimes a buggy android app might send us bogus settings - void resetRadioConfig(); + /** Reinit radio config if needed, because either: + * a) sometimes a buggy android app might send us bogus settings or + * b) the client set factory_reset + * + * @return true if the config was completely reset, in that case, we should send it back to the client + */ + bool resetRadioConfig(); /// given a subpacket sniffed from the network, update our DB state /// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index caadf8563..9ae5955d5 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -243,7 +243,10 @@ void PhoneAPI::handleSetRadio(const RadioConfig &r) { radioConfig = r; - service.reloadConfig(); + bool didReset = service.reloadConfig(); + if (didReset) { + state = STATE_SEND_MY_INFO; // Squirt a completely new set of configs to the client + } } /** diff --git a/src/mesh/mesh.pb.c b/src/mesh/mesh.pb.c index ddc720cf3..b2d1ceb23 100644 --- a/src/mesh/mesh.pb.c +++ b/src/mesh/mesh.pb.c @@ -27,7 +27,7 @@ PB_BIND(MeshPacket, MeshPacket, 2) PB_BIND(ChannelSettings, ChannelSettings, AUTO) -PB_BIND(RadioConfig, RadioConfig, AUTO) +PB_BIND(RadioConfig, RadioConfig, 2) PB_BIND(RadioConfig_UserPreferences, RadioConfig_UserPreferences, 2) diff --git a/src/mesh/mesh.pb.h b/src/mesh/mesh.pb.h index 64b2758c3..6fbc79f7c 100644 --- a/src/mesh/mesh.pb.h +++ b/src/mesh/mesh.pb.h @@ -108,6 +108,8 @@ typedef struct _RadioConfig_UserPreferences { char wifi_ssid[33]; char wifi_password[64]; bool wifi_ap_mode; + char region[6]; + bool factory_reset; pb_size_t ignore_incoming_count; uint32_t ignore_incoming[3]; } RadioConfig_UserPreferences; @@ -248,7 +250,7 @@ typedef struct _ToRadio { #define MeshPacket_init_default {0, 0, 0, {SubPacket_init_default}, 0, 0, 0, 0, 0} #define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0} #define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default, false, ChannelSettings_init_default} -#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, {0, 0, 0}} +#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, "", 0, 0, {0, 0, 0}} #define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0} #define MyNodeInfo_init_default {0, 0, 0, "", "", "", 0, 0, 0, 0, 0, 0, 0, 0} #define DeviceState_init_default {false, RadioConfig_init_default, false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0} @@ -264,7 +266,7 @@ typedef struct _ToRadio { #define MeshPacket_init_zero {0, 0, 0, {SubPacket_init_zero}, 0, 0, 0, 0, 0} #define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0} #define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero, false, ChannelSettings_init_zero} -#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, {0, 0, 0}} +#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, "", 0, 0, {0, 0, 0}} #define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0} #define MyNodeInfo_init_zero {0, 0, 0, "", "", "", 0, 0, 0, 0, 0, 0, 0, 0} #define DeviceState_init_zero {false, RadioConfig_init_zero, false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0} @@ -322,7 +324,9 @@ typedef struct _ToRadio { #define RadioConfig_UserPreferences_wifi_ssid_tag 12 #define RadioConfig_UserPreferences_wifi_password_tag 13 #define RadioConfig_UserPreferences_wifi_ap_mode_tag 14 -#define RadioConfig_UserPreferences_ignore_incoming_tag 102 +#define RadioConfig_UserPreferences_region_tag 15 +#define RadioConfig_UserPreferences_factory_reset_tag 100 +#define RadioConfig_UserPreferences_ignore_incoming_tag 103 #define RouteDiscovery_route_tag 2 #define User_id_tag 1 #define User_long_name_tag 2 @@ -477,7 +481,9 @@ X(a, STATIC, SINGULAR, UINT32, min_wake_secs, 11) \ X(a, STATIC, SINGULAR, STRING, wifi_ssid, 12) \ X(a, STATIC, SINGULAR, STRING, wifi_password, 13) \ X(a, STATIC, SINGULAR, BOOL, wifi_ap_mode, 14) \ -X(a, STATIC, REPEATED, UINT32, ignore_incoming, 102) +X(a, STATIC, SINGULAR, STRING, region, 15) \ +X(a, STATIC, SINGULAR, BOOL, factory_reset, 100) \ +X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103) #define RadioConfig_UserPreferences_CALLBACK NULL #define RadioConfig_UserPreferences_DEFAULT NULL @@ -613,11 +619,11 @@ extern const pb_msgdesc_t ManufacturingData_msg; #define SubPacket_size 274 #define MeshPacket_size 313 #define ChannelSettings_size 84 -#define RadioConfig_size 277 -#define RadioConfig_UserPreferences_size 188 +#define RadioConfig_size 287 +#define RadioConfig_UserPreferences_size 198 #define NodeInfo_size 132 #define MyNodeInfo_size 110 -#define DeviceState_size 5429 +#define DeviceState_size 5439 #define DebugString_size 258 #define FromRadio_size 322 #define ToRadio_size 316 From c57a9a86132ddf15f0c4869a042566cef2124544 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sat, 19 Sep 2020 11:24:55 -0700 Subject: [PATCH 17/34] Update from my laptop --- src/meshwifi/meshhttp.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index 0f8988ddf..d341b8638 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -27,8 +27,11 @@ void handleWebResponse() void initWebServer() { webserver.onNotFound(handleNotFound); - // webserver.on("/", handleJSONChatHistory); - // webserver.on("/json/chat/history", handleJSONChatHistory); + 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/user", handleJSONChatHistory); + webserver.on("/json/stats", handleJSONChatHistory); webserver.on("/hotspot-detect.html", handleHotspot); webserver.on("/", handleRoot); webserver.begin(); @@ -57,7 +60,8 @@ void handleJSONChatHistory() void handleNotFound() { - String message = "File Not Found\n\n"; + String message = ""; + message += "File Not Found\n\n"; message += "URI: "; message += webserver.uri(); message += "\nMethod: "; @@ -71,8 +75,6 @@ void handleNotFound() } Serial.println(message); webserver.send(404, "text/plain", message); - /* - */ } /* From 7c44daf8f47fc8c19b9e0cfcedc4c1e10e9ac0dd Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sat, 19 Sep 2020 12:50:43 -0700 Subject: [PATCH 18/34] pushing my chances to personal branch so i can get the changes from the laptop --- src/meshwifi/meshhttp.cpp | 11 +++++++++++ src/meshwifi/meshwifi.cpp | 13 +++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index 0f8988ddf..863486557 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -8,6 +8,17 @@ WebServer webserver(80); +struct message { + char sender[10]; + char message[250]; + int32_t gpsLat; + int32_t gpsLong; + uint32_t time; + bool fromMe; +}; + +struct message arrayMessages[50]; + String something = ""; String sender = ""; diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index a88ed6ae3..112b5034d 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -16,6 +16,11 @@ bool isWifiAvailable() const char *wifiPsw = radioConfig.preferences.wifi_password; if (*wifiName && *wifiPsw) { + + + // + + return 1; } else { return 0; @@ -26,7 +31,7 @@ bool isWifiAvailable() void deinitWifi() { /* - Note from Jm (Sept 16, 2020): + Note from Jm (jm@casler.org - Sept 16, 2020): A bug in the ESP32 SDK was introduced in Oct 2019 that keeps the WiFi radio from turning back on after it's shut off. See: @@ -52,16 +57,16 @@ void initWifi() const char *wifiName = radioConfig.preferences.wifi_ssid; const char *wifiPsw = radioConfig.preferences.wifi_password; - /* - if (1) { + if (0) { radioConfig.preferences.wifi_ap_mode = 1; strcpy(radioConfig.preferences.wifi_ssid, "MeshTest2"); strcpy(radioConfig.preferences.wifi_password, "12345678"); } else { radioConfig.preferences.wifi_ap_mode = 0; - strcpy(radioConfig.preferences.wifi_ssid, "meshtastic"); + strcpy(radioConfig.preferences.wifi_ssid, "meshtastic1"); strcpy(radioConfig.preferences.wifi_password, "meshtastic!"); } + /* */ if (*wifiName && *wifiPsw) { From 9e9c50e6d8f10a9eb07259f75ef4e8f211ff5935 Mon Sep 17 00:00:00 2001 From: geeksville Date: Sat, 19 Sep 2020 12:54:49 -0700 Subject: [PATCH 19/34] Add API server on port 4403 (kinda a WIP, seems to work but I haven't finished the python client code) --- proto | 2 +- src/esp32/WiFiServerAPI.cpp | 2 +- src/main.cpp | 6 ++++-- src/meshwifi/meshwifi.cpp | 32 ++++++++++++++++++++++++++------ src/meshwifi/meshwifi.h | 6 +++++- src/nrf52/wifi-nrf52.cpp | 5 ++++- 6 files changed, 41 insertions(+), 12 deletions(-) diff --git a/proto b/proto index ce422b7c4..4e431c841 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit ce422b7c448906c6fee3eef64bbd41adfbc990f0 +Subproject commit 4e431c841015edfdde925acf5ee4ac0a2272edff diff --git a/src/esp32/WiFiServerAPI.cpp b/src/esp32/WiFiServerAPI.cpp index b5d555605..974b0f3c1 100644 --- a/src/esp32/WiFiServerAPI.cpp +++ b/src/esp32/WiFiServerAPI.cpp @@ -44,7 +44,7 @@ WiFiServerPort::WiFiServerPort() : WiFiServer(MESHTASTIC_PORTNUM) {} void WiFiServerPort::init() { - DEBUG_MSG("Listening on TCP port %d\n", MESHTASTIC_PORTNUM); + DEBUG_MSG("API server sistening on TCP port %d\n", MESHTASTIC_PORTNUM); begin(); } diff --git a/src/main.cpp b/src/main.cpp index b0d133f22..bb4b12e10 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -37,12 +37,12 @@ #include "SPILock.h" #include "graphics/Screen.h" #include "main.h" +#include "meshwifi/meshhttp.h" +#include "meshwifi/meshwifi.h" #include "sleep.h" #include "timing.h" #include #include -#include "meshwifi/meshwifi.h" -#include "meshwifi/meshhttp.h" // #include #ifndef NO_ESP32 @@ -395,6 +395,8 @@ void loop() userButtonAlt.tick(); #endif + loopWifi(); + // Show boot screen for first 3 seconds, then switch to normal operation. static bool showingBootScreen = true; if (showingBootScreen && (timing::millis() > 3000)) { diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index f395ff7b0..b5bef9646 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -1,16 +1,18 @@ #include "meshwifi.h" #include "NodeDB.h" +#include "WiFiServerAPI.h" #include "configuration.h" #include "main.h" #include "meshwifi/meshhttp.h" -#include #include +#include static void WiFiEvent(WiFiEvent_t event); DNSServer dnsServer; +static WiFiServerPort *apiPort; -bool isWifiAvailable() +bool isWifiAvailable() { const char *wifiName = radioConfig.preferences.wifi_ssid; const char *wifiPsw = radioConfig.preferences.wifi_password; @@ -66,7 +68,7 @@ void initWifi() if (*wifiName && *wifiPsw) { if (radioConfig.preferences.wifi_ap_mode) { - + IPAddress apIP(192, 168, 42, 1); WiFi.onEvent(WiFiEvent); @@ -76,7 +78,6 @@ void initWifi() dnsServer.start(53, "*", apIP); - } else { WiFi.mode(WIFI_MODE_STA); WiFi.onEvent(WiFiEvent); @@ -94,6 +95,23 @@ void initWifi() DEBUG_MSG("Not using WIFI\n"); } +/// Perform idle loop processing required by the wifi layer +void loopWifi() +{ + // FIXME, once we have coroutines - just use a coroutine instead of this nasty loopWifi() + if (apiPort) + apiPort->loop(); +} + +static void initApiServer() +{ + // Start API server on port 4403 + if (!apiPort) { + apiPort = new WiFiServerPort(); + apiPort->init(); + } +} + static void WiFiEvent(WiFiEvent_t event) { DEBUG_MSG("************ [WiFi-event] event: %d ************\n", event); @@ -129,6 +147,7 @@ static void WiFiEvent(WiFiEvent_t event) // Start web server initWebServer(); + initApiServer(); break; case SYSTEM_EVENT_STA_LOST_IP: @@ -152,6 +171,7 @@ static void WiFiEvent(WiFiEvent_t event) // Start web server initWebServer(); + initApiServer(); break; case SYSTEM_EVENT_AP_STOP: @@ -189,11 +209,11 @@ static void WiFiEvent(WiFiEvent_t event) break; default: break; - } } -void handleDNSResponse() { +void handleDNSResponse() +{ if (radioConfig.preferences.wifi_ap_mode) { dnsServer.processNextRequest(); } diff --git a/src/meshwifi/meshwifi.h b/src/meshwifi/meshwifi.h index 44fff707f..0b74592f3 100644 --- a/src/meshwifi/meshwifi.h +++ b/src/meshwifi/meshwifi.h @@ -5,12 +5,16 @@ #include #ifdef HAS_WIFI -#include #include +#include #endif void initWifi(); void deinitWifi(); + +/// Perform idle loop processing required by the wifi layer +void loopWifi(); + bool isWifiAvailable(); void handleDNSResponse(); diff --git a/src/nrf52/wifi-nrf52.cpp b/src/nrf52/wifi-nrf52.cpp index e4885add7..30321e5e4 100644 --- a/src/nrf52/wifi-nrf52.cpp +++ b/src/nrf52/wifi-nrf52.cpp @@ -10,4 +10,7 @@ bool isWifiAvailable() return false; } -void handleWebResponse() {} \ No newline at end of file +void handleWebResponse() {} + +/// Perform idle loop processing required by the wifi layer +void loopWifi() {} \ No newline at end of file From 464a42258fc625c9b16a15773cb13272be4e444b Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sat, 19 Sep 2020 16:38:59 -0700 Subject: [PATCH 20/34] Fix for "Wifi in station mode sometimes enters loops of repeatedly joining... #420" Fix for Wifi in station mode sometimes enters loops of repeatedly joining... #420 --- src/graphics/Screen.cpp | 48 ++++++++++++++++----------------------- src/meshwifi/meshhttp.cpp | 20 ++++++++++++++-- src/meshwifi/meshwifi.cpp | 33 +++++++++++++++++++-------- src/meshwifi/meshwifi.h | 4 +++- 4 files changed, 64 insertions(+), 41 deletions(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 7e85fe8a4..d0d0d9214 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -31,8 +31,8 @@ along with this program. If not, see . #include "graphics/images.h" #include "main.h" #include "mesh-pb-constants.h" -#include "utils.h" #include "meshwifi/meshwifi.h" +#include "utils.h" using namespace meshtastic; /** @todo remove */ @@ -715,7 +715,6 @@ void Screen::drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiStat screen->debugInfo.drawFrameWiFi(display, state, x, y); } - // restore our regular frame list void Screen::setFrames() { @@ -854,12 +853,17 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i if (radioConfig.preferences.wifi_ap_mode) { 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")); } else { display->drawString(x, y, String("WiFi - Connected")); + + display->drawString(x + SCREEN_WIDTH - display->getStringWidth("RSSI " + String(WiFi.RSSI())), y, + "RSSI " + String(WiFi.RSSI())); + } + if (radioConfig.preferences.wifi_ap_mode) { display->drawString(x, y + FONT_HEIGHT * 1, "IP " + String(WiFi.softAPIP().toString().c_str())); } else { @@ -868,7 +872,7 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i display->drawString(x, y + FONT_HEIGHT * 2, "SSID " + String(wifiName)); display->drawString(x, y + FONT_HEIGHT * 3, "PWD " + String(wifiPsw)); - + /* Display a heartbeat pixel that blinks every time the frame is redrawn */ #ifdef SHOW_REDRAWS if (heartbeat) @@ -878,7 +882,6 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i #endif } - void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { displayedNodeNum = 0; // Not currently showing a node pane @@ -889,29 +892,21 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat display->setTextAlignment(TEXT_ALIGN_LEFT); char batStr[20]; - if (powerStatus->getHasBattery()) - { + if (powerStatus->getHasBattery()) { int batV = powerStatus->getBatteryVoltageMv() / 1000; int batCv = (powerStatus->getBatteryVoltageMv() % 1000) / 10; - snprintf(batStr, sizeof(batStr), "B %01d.%02dV %3d%% %c%c", - batV, - batCv, - powerStatus->getBatteryChargePercent(), - powerStatus->getIsCharging() ? '+' : ' ', - powerStatus->getHasUSB() ? 'U' : ' '); + snprintf(batStr, sizeof(batStr), "B %01d.%02dV %3d%% %c%c", batV, batCv, powerStatus->getBatteryChargePercent(), + powerStatus->getIsCharging() ? '+' : ' ', powerStatus->getHasUSB() ? 'U' : ' '); // Line 1 display->drawString(x, y, batStr); - } - else - { + } else { // Line 1 display->drawString(x, y, String("USB")); - } + } - - //TODO: Display status of the BT radio + // TODO: Display status of the BT radio // display->drawString(x + SCREEN_WIDTH - display->getStringWidth("BT On"), y, "BT On"); // Line 2 @@ -925,20 +920,15 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat minutes %= 60; hours %= 24; - display->drawString(x, y + FONT_HEIGHT * 1, String(days) + "d " - + (hours < 10 ? "0" : "") + String(hours) + ":" - + (minutes < 10 ? "0" : "") + String(minutes) + ":" - + (seconds < 10 ? "0" : "") + String(seconds)); - display->drawString(x + SCREEN_WIDTH - display->getStringWidth("Mode " + String(channelSettings.modem_config)), y + FONT_HEIGHT * 1, "Mode " + String(channelSettings.modem_config)); - - // Line 3 - // TODO: Use this line for WiFi information. - // display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth("WiFi: 192.168.0.100"))) / 2, y + FONT_HEIGHT * 2, "WiFi: 192.168.0.100"); + display->drawString(x, y + FONT_HEIGHT * 1, + String(days) + "d " + (hours < 10 ? "0" : "") + String(hours) + ":" + (minutes < 10 ? "0" : "") + + String(minutes) + ":" + (seconds < 10 ? "0" : "") + String(seconds)); + display->drawString(x + SCREEN_WIDTH - display->getStringWidth("Mode " + String(channelSettings.modem_config)), + y + FONT_HEIGHT * 1, "Mode " + String(channelSettings.modem_config)); // Line 4 drawGPScoordinates(display, x, y + FONT_HEIGHT * 3, gpsStatus); - /* Display a heartbeat pixel that blinks every time the frame is redrawn */ #ifdef SHOW_REDRAWS if (heartbeat) diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index 4899e6ae9..6b3776730 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -8,7 +8,9 @@ WebServer webserver(80); -struct message { +const uint16_t maxMessages = 50; + +struct message_t { char sender[10]; char message[250]; int32_t gpsLat; @@ -17,7 +19,12 @@ struct message { bool fromMe; }; -struct message arrayMessages[50]; +struct messages_t +{ + message_t history[maxMessages]; // 900 positions to save up to 1200 seconds (15 minutes). uInt for each temerature sensor, Input and Setpoint. +}; + +messages_t messages_history; String something = ""; String sender = ""; @@ -50,6 +57,7 @@ void initWebServer() void handleJSONChatHistory() { + int i; String out = ""; out += "{\n"; @@ -61,6 +69,14 @@ void handleJSONChatHistory() out += "\"" + something + "\""; out += "]\n"; + for (i = 0; i < maxMessages; i++) { + out += "["; + out += "\"" + String(messages_history.history[i].sender) + "\""; + out += ","; + out += "\"" + String(messages_history.history[i].message) + "\""; + out += "]\n"; + } + out += "\n"; out += " }\n"; out += "}\n"; diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index 112b5034d..e31065ef9 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -17,9 +17,7 @@ bool isWifiAvailable() if (*wifiName && *wifiPsw) { - - // - + // Once every 10 seconds, try to reconnect. return 1; } else { @@ -43,7 +41,7 @@ void deinitWifi() WiFi.mode(WIFI_MODE_NULL); DEBUG_MSG("WiFi Turned Off\n"); - WiFi.printDiag(Serial); + // WiFi.printDiag(Serial); } // Startup WiFi @@ -57,17 +55,17 @@ void initWifi() const char *wifiName = radioConfig.preferences.wifi_ssid; const char *wifiPsw = radioConfig.preferences.wifi_password; + /* if (0) { radioConfig.preferences.wifi_ap_mode = 1; strcpy(radioConfig.preferences.wifi_ssid, "MeshTest2"); strcpy(radioConfig.preferences.wifi_password, "12345678"); } else { radioConfig.preferences.wifi_ap_mode = 0; - strcpy(radioConfig.preferences.wifi_ssid, "meshtastic1"); + strcpy(radioConfig.preferences.wifi_ssid, "meshtastic"); strcpy(radioConfig.preferences.wifi_password, "meshtastic!"); } - /* - */ + */ if (*wifiName && *wifiPsw) { if (radioConfig.preferences.wifi_ap_mode) { @@ -120,9 +118,9 @@ static void WiFiEvent(WiFiEvent_t event) break; case SYSTEM_EVENT_STA_DISCONNECTED: DEBUG_MSG("Disconnected from WiFi access point\n"); + // Event 5 - // Reconnect WiFi - initWifi(); + reconnectWiFi(); break; case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: DEBUG_MSG("Authentication mode of access point has changed\n"); @@ -201,4 +199,21 @@ void handleDNSResponse() if (radioConfig.preferences.wifi_ap_mode) { dnsServer.processNextRequest(); } +} + +void reconnectWiFi() +{ + const char *wifiName = radioConfig.preferences.wifi_ssid; + const char *wifiPsw = radioConfig.preferences.wifi_password; + + if (radioConfig.has_preferences) { + + if (*wifiName && *wifiPsw) { + + DEBUG_MSG("... Reconnecting to WiFi access point"); + + WiFi.mode(WIFI_MODE_STA); + WiFi.begin(wifiName, wifiPsw); + } + } } \ No newline at end of file diff --git a/src/meshwifi/meshwifi.h b/src/meshwifi/meshwifi.h index 44fff707f..bcafa700a 100644 --- a/src/meshwifi/meshwifi.h +++ b/src/meshwifi/meshwifi.h @@ -5,8 +5,8 @@ #include #ifdef HAS_WIFI -#include #include +#include #endif void initWifi(); @@ -14,3 +14,5 @@ void deinitWifi(); bool isWifiAvailable(); void handleDNSResponse(); + +void reconnectWiFi(); From 377f0bda5d9222d2443df950dab1b52847195fc0 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sat, 19 Sep 2020 17:15:03 -0700 Subject: [PATCH 21/34] Add more detail on the connection status on the screen #422 --- src/graphics/Screen.cpp | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index d0d0d9214..64ff06e73 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -860,14 +860,35 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i display->drawString(x + SCREEN_WIDTH - display->getStringWidth("RSSI " + String(WiFi.RSSI())), y, "RSSI " + String(WiFi.RSSI())); - } + /* + - WL_CONNECTED: assigned when connected to a WiFi network; + WL_NO_SHIELD: assigned when no WiFi shield is present; + WL_IDLE_STATUS: it is a temporary status assigned when WiFi.begin() is called and remains active until the number of attempts expires (resulting in WL_CONNECT_FAILED) or a connection is established (resulting in WL_CONNECTED); + - WL_NO_SSID_AVAIL: assigned when no SSID are available; + WL_SCAN_COMPLETED: assigned when the scan networks is completed; + - WL_CONNECT_FAILED: assigned when the connection fails for all the attempts; + - WL_CONNECTION_LOST: assigned when the connection is lost; + - WL_DISCONNECTED: assigned when disconnected from a network; + */ - if (radioConfig.preferences.wifi_ap_mode) { - display->drawString(x, y + FONT_HEIGHT * 1, "IP " + String(WiFi.softAPIP().toString().c_str())); + if (WiFi.status() == WL_CONNECTED) { + if (radioConfig.preferences.wifi_ap_mode) { + display->drawString(x, y + FONT_HEIGHT * 1, "IP " + String(WiFi.softAPIP().toString().c_str())); + } else { + display->drawString(x, y + FONT_HEIGHT * 1, "IP " + String(WiFi.localIP().toString().c_str())); + } + } else if (WiFi.status() == WL_NO_SSID_AVAIL) { + display->drawString(x, y + FONT_HEIGHT * 1, "SSID Not Found"); + } else if (WiFi.status() == WL_CONNECTION_LOST) { + display->drawString(x, y + FONT_HEIGHT * 1, "Connection Lost"); + } else if (WiFi.status() == WL_CONNECT_FAILED) { + display->drawString(x, y + FONT_HEIGHT * 1, "Connection Failed"); + } else if (WiFi.status() == WL_DISCONNECTED) { + display->drawString(x, y + FONT_HEIGHT * 1, "Disconnected"); } else { - display->drawString(x, y + FONT_HEIGHT * 1, "IP " + String(WiFi.localIP().toString().c_str())); + display->drawString(x, y + FONT_HEIGHT * 1, "Unknown Status"); } display->drawString(x, y + FONT_HEIGHT * 2, "SSID " + String(wifiName)); From d890068acbbdfb4ea0935c59c2e87f8347026a40 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sat, 19 Sep 2020 21:58:21 -0700 Subject: [PATCH 22/34] dev-wifi: Detailed error reporting of reason why WiFi didn't connect #424 --- src/graphics/Screen.cpp | 86 ++++++++++++++++++++++++++++++++++----- src/meshwifi/meshwifi.cpp | 17 +++++++- src/meshwifi/meshwifi.h | 2 + 3 files changed, 93 insertions(+), 12 deletions(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 64ff06e73..a108cd022 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -852,11 +852,11 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i display->setTextAlignment(TEXT_ALIGN_LEFT); 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) { - display->drawString(x, y, String("WiFi - Not Connected")); + display->drawString(x, y, String("WiFi: Not Connected")); } else { - display->drawString(x, y, String("WiFi - Connected")); + display->drawString(x, y, String("WiFi: Connected")); display->drawString(x + SCREEN_WIDTH - display->getStringWidth("RSSI " + String(WiFi.RSSI())), y, "RSSI " + String(WiFi.RSSI())); @@ -864,20 +864,22 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i /* - WL_CONNECTED: assigned when connected to a WiFi network; - WL_NO_SHIELD: assigned when no WiFi shield is present; - WL_IDLE_STATUS: it is a temporary status assigned when WiFi.begin() is called and remains active until the number of attempts expires (resulting in WL_CONNECT_FAILED) or a connection is established (resulting in WL_CONNECTED); - WL_NO_SSID_AVAIL: assigned when no SSID are available; - WL_SCAN_COMPLETED: assigned when the scan networks is completed; - WL_CONNECT_FAILED: assigned when the connection fails for all the attempts; - WL_CONNECTION_LOST: assigned when the connection is lost; - WL_DISCONNECTED: assigned when disconnected from a network; + - WL_IDLE_STATUS: it is a temporary status assigned when WiFi.begin() is called and remains active until the number of + attempts expires (resulting in WL_CONNECT_FAILED) or a connection is established (resulting in WL_CONNECTED); + - WL_SCAN_COMPLETED: assigned when the scan networks is completed; + - WL_NO_SHIELD: assigned when no WiFi shield is present; + */ if (WiFi.status() == WL_CONNECTED) { if (radioConfig.preferences.wifi_ap_mode) { - display->drawString(x, y + FONT_HEIGHT * 1, "IP " + String(WiFi.softAPIP().toString().c_str())); + display->drawString(x, y + FONT_HEIGHT * 1, "IP: " + String(WiFi.softAPIP().toString().c_str())); } else { - display->drawString(x, y + FONT_HEIGHT * 1, "IP " + String(WiFi.localIP().toString().c_str())); + display->drawString(x, y + FONT_HEIGHT * 1, "IP: " + String(WiFi.localIP().toString().c_str())); } } else if (WiFi.status() == WL_NO_SSID_AVAIL) { display->drawString(x, y + FONT_HEIGHT * 1, "SSID Not Found"); @@ -887,12 +889,74 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i display->drawString(x, y + FONT_HEIGHT * 1, "Connection Failed"); } else if (WiFi.status() == WL_DISCONNECTED) { display->drawString(x, y + FONT_HEIGHT * 1, "Disconnected"); + } else if (WiFi.status() == WL_IDLE_STATUS) { + display->drawString(x, y + FONT_HEIGHT * 1, "Idle ... Reconnecting"); } else { - display->drawString(x, y + FONT_HEIGHT * 1, "Unknown Status"); + // Codes: + // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html#wi-fi-reason-code + if (getWifiDisconnectReason() == 2) { + display->drawString(x, y + FONT_HEIGHT * 1, "Authentication Invalid"); + } else if (getWifiDisconnectReason() == 3) { + display->drawString(x, y + FONT_HEIGHT * 1, "De-authenticated"); + } else if (getWifiDisconnectReason() == 4) { + display->drawString(x, y + FONT_HEIGHT * 1, "Disassociated Expired"); + } else if (getWifiDisconnectReason() == 5) { + display->drawString(x, y + FONT_HEIGHT * 1, "AP - Too Many Clients"); + } else if (getWifiDisconnectReason() == 6) { + display->drawString(x, y + FONT_HEIGHT * 1, "NOT_AUTHED"); + } else if (getWifiDisconnectReason() == 7) { + display->drawString(x, y + FONT_HEIGHT * 1, "NOT_ASSOCED"); + } else if (getWifiDisconnectReason() == 8) { + display->drawString(x, y + FONT_HEIGHT * 1, "Disassociated"); + } else if (getWifiDisconnectReason() == 9) { + display->drawString(x, y + FONT_HEIGHT * 1, "ASSOC_NOT_AUTHED"); + } else if (getWifiDisconnectReason() == 10) { + display->drawString(x, y + FONT_HEIGHT * 1, "DISASSOC_PWRCAP_BAD"); + } else if (getWifiDisconnectReason() == 11) { + display->drawString(x, y + FONT_HEIGHT * 1, "DISASSOC_SUPCHAN_BAD"); + } else if (getWifiDisconnectReason() == 13) { + display->drawString(x, y + FONT_HEIGHT * 1, "IE_INVALID"); + } else if (getWifiDisconnectReason() == 14) { + display->drawString(x, y + FONT_HEIGHT * 1, "MIC_FAILURE"); + } else if (getWifiDisconnectReason() == 15) { + display->drawString(x, y + FONT_HEIGHT * 1, "4WAY_HANDSHAKE_TIMEOUT"); + } else if (getWifiDisconnectReason() == 16) { + display->drawString(x, y + FONT_HEIGHT * 1, "GROUP_KEY_UPDATE_TIMEOUT"); + } else if (getWifiDisconnectReason() == 17) { + display->drawString(x, y + FONT_HEIGHT * 1, "IE_IN_4WAY_DIFFERS"); + } else if (getWifiDisconnectReason() == 18) { + display->drawString(x, y + FONT_HEIGHT * 1, "Invalid Group Cipher"); + } else if (getWifiDisconnectReason() == 19) { + display->drawString(x, y + FONT_HEIGHT * 1, "Invalid Pairwise Cipher"); + } else if (getWifiDisconnectReason() == 20) { + display->drawString(x, y + FONT_HEIGHT * 1, "AKMP_INVALID"); + } else if (getWifiDisconnectReason() == 21) { + display->drawString(x, y + FONT_HEIGHT * 1, "UNSUPP_RSN_IE_VERSION"); + } else if (getWifiDisconnectReason() == 22) { + display->drawString(x, y + FONT_HEIGHT * 1, "INVALID_RSN_IE_CAP"); + } else if (getWifiDisconnectReason() == 23) { + display->drawString(x, y + FONT_HEIGHT * 1, "802_1X_AUTH_FAILED"); + } else if (getWifiDisconnectReason() == 24) { + display->drawString(x, y + FONT_HEIGHT * 1, "CIPHER_SUITE_REJECTED"); + } else if (getWifiDisconnectReason() == 200) { + display->drawString(x, y + FONT_HEIGHT * 1, "BEACON_TIMEOUT"); + } else if (getWifiDisconnectReason() == 201) { + display->drawString(x, y + FONT_HEIGHT * 1, "NO_AP_FOUND"); + } else if (getWifiDisconnectReason() == 202) { + display->drawString(x, y + FONT_HEIGHT * 1, "AUTH_FAIL"); + } else if (getWifiDisconnectReason() == 203) { + display->drawString(x, y + FONT_HEIGHT * 1, "ASSOC_FAIL"); + } else if (getWifiDisconnectReason() == 204) { + display->drawString(x, y + FONT_HEIGHT * 1, "HANDSHAKE_TIMEOUT"); + } else if (getWifiDisconnectReason() == 205) { + display->drawString(x, y + FONT_HEIGHT * 1, "CONNECTION_FAIL"); + } else { + display->drawString(x, y + FONT_HEIGHT * 1, "Unknown Status"); + } } - display->drawString(x, y + FONT_HEIGHT * 2, "SSID " + String(wifiName)); - display->drawString(x, y + FONT_HEIGHT * 3, "PWD " + String(wifiPsw)); + display->drawString(x, y + FONT_HEIGHT * 2, "SSID: " + String(wifiName)); + display->drawString(x, y + FONT_HEIGHT * 3, "PWD: " + String(wifiPsw)); /* Display a heartbeat pixel that blinks every time the frame is redrawn */ #ifdef SHOW_REDRAWS diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index 1e86e4d66..ad8a88fa2 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -8,10 +8,13 @@ #include static void WiFiEvent(WiFiEvent_t event); +// static void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info); DNSServer dnsServer; static WiFiServerPort *apiPort; +uint8_t wifiDisconnectReason = 0; + bool isWifiAvailable() { const char *wifiName = radioConfig.preferences.wifi_ssid; @@ -86,6 +89,14 @@ void initWifi() WiFi.onEvent(WiFiEvent); // esp_wifi_set_ps(WIFI_PS_NONE); // Disable power saving + WiFiEventId_t eventID = WiFi.onEvent( + [](WiFiEvent_t event, WiFiEventInfo_t info) { + Serial.print("\n-------------- WiFi lost connection. Reason: "); + Serial.println(info.disconnected.reason); + // wifiDisconnectReason = info.disconnected.reason; + }, + WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED); + DEBUG_MSG("JOINING WIFI: ssid=%s\n", wifiName); if (WiFi.begin(wifiName, wifiPsw) == WL_CONNECTED) { DEBUG_MSG("MY IP ADDRESS: %s\n", WiFi.localIP().toString().c_str()); @@ -114,7 +125,6 @@ static void initApiServer() apiPort->init(); } } - static void WiFiEvent(WiFiEvent_t event) { DEBUG_MSG("************ [WiFi-event] event: %d ************\n", event); @@ -237,4 +247,9 @@ void reconnectWiFi() WiFi.begin(wifiName, wifiPsw); } } +} + +uint8_t getWifiDisconnectReason() +{ + return wifiDisconnectReason; } \ No newline at end of file diff --git a/src/meshwifi/meshwifi.h b/src/meshwifi/meshwifi.h index 8898c0ad8..d38b2a41e 100644 --- a/src/meshwifi/meshwifi.h +++ b/src/meshwifi/meshwifi.h @@ -20,3 +20,5 @@ bool isWifiAvailable(); void handleDNSResponse(); void reconnectWiFi(); + +uint8_t getWifiDisconnectReason(); \ No newline at end of file From 3352fae64ce2ff67da9d83479dcd3de5285cd0cf Mon Sep 17 00:00:00 2001 From: geeksville Date: Mon, 21 Sep 2020 12:41:39 -0700 Subject: [PATCH 23/34] fix #371 allow button while using API. also don't let tbeams sleep if they have USB power --- docs/software/power.md | 10 ++++++++-- src/Power.cpp | 3 +++ src/PowerFSM.cpp | 29 +++++++++++++++++++++++++---- src/PowerFSM.h | 4 +++- src/SerialConsole.cpp | 2 ++ src/main.cpp | 2 +- 6 files changed, 42 insertions(+), 8 deletions(-) diff --git a/docs/software/power.md b/docs/software/power.md index cd0d2c913..e98e5bd0d 100644 --- a/docs/software/power.md +++ b/docs/software/power.md @@ -32,11 +32,15 @@ From lower to higher power consumption. onEntry: setBluetoothOn(true) onExit: -- full on (ON) - Everything is on +- serial API usage (SERIAL) - Screen is on, device doesn't sleep, bluetooth off + onEntry: setBluetooth off, screen on + onExit: + +- full on (ON) - Everything is on, can eventually timeout and lower to a lower power state onEntry: setBluetoothOn(true), screen.setOn(true) onExit: screen.setOn(false) -- serial API usage (SERIAL) - Screen is on, device doesn't sleep, bluetooth off +- has power (POWER) - Screen is on, device doesn't sleep, bluetooth on, will stay in this state as long as we have power onEntry: setBluetooth off, screen on onExit: @@ -56,9 +60,11 @@ From lower to higher power consumption. - While in NB/DARK/ON: If we receive EVENT_NODEDB_UPDATED we transition to ON (so the new screen can be shown) - While in DARK: While the phone talks to us over BLE (EVENT_CONTACT_FROM_PHONE) reset any sleep timers and stay in DARK (needed for bluetooth sw update and nice user experience if the user is reading/replying to texts) - while in LS/NB/DARK: if SERIAL_CONNECTED, go to serial +- while in any state: if we have AC power, go to POWER ### events that decrease cpu activity +- While in POWER: if lose AC go to ON - While in SERIAL: if SERIAL_DISCONNECTED, go to NB - While in ON: If PRESS event occurs, reset screen_on_secs timer and tell the screen to handle the pess - While in ON: If it has been more than screen_on_secs since a press, lower to DARK diff --git a/src/Power.cpp b/src/Power.cpp index 1145c51c4..7d032b666 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -119,6 +119,7 @@ void Power::readPowerStatus() const PowerStatus powerStatus = PowerStatus(hasBattery ? OptTrue : OptFalse, batteryLevel->isVBUSPlug() ? OptTrue : OptFalse, batteryLevel->isChargeing() ? OptTrue : OptFalse, batteryVoltageMv, batteryChargePercent); + DEBUG_MSG("Read power stat %d\n", powerStatus.getHasUSB()); newStatus.notifyObservers(&powerStatus); // If we have a battery at all and it is less than 10% full, force deep sleep @@ -237,9 +238,11 @@ void Power::loop() } 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"); diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 128947bcd..f72e5842a 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -4,8 +4,8 @@ #include "MeshService.h" #include "NodeDB.h" #include "configuration.h" -#include "main.h" #include "graphics/Screen.h" +#include "main.h" #include "sleep.h" #include "target_specific.h" @@ -123,6 +123,12 @@ static void serialEnter() screen.setOn(true); } +static void powerEnter() +{ + screen.setOn(true); + setBluetoothEnable(true); +} + static void onEnter() { screen.setOn(true); @@ -155,16 +161,20 @@ 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"); Fsm powerFSM(&stateBOOT); void PowerFSM_setup() { - powerFSM.add_timed_transition(&stateBOOT, &stateON, 3 * 1000, NULL, "boot timeout"); + // If we already have AC power go to POWER state after init, otherwise go to ON + bool hasPower = 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"); powerFSM.add_transition(&stateLS, &stateDARK, EVENT_WAKE_TIMER, wakeForPing, "Wake timer"); - // Note we don't really use this transition, because when we wake from light sleep we _always_ transition to NB and then it - // handles things powerFSM.add_transition(&stateLS, &stateNB, EVENT_RECEIVED_PACKET, NULL, "Received packet"); + // Note we don't really use this transition, because when we wake from light sleep we _always_ transition to NB and then + // it handles things powerFSM.add_transition(&stateLS, &stateNB, EVENT_RECEIVED_PACKET, NULL, "Received packet"); powerFSM.add_transition(&stateNB, &stateNB, EVENT_RECEIVED_PACKET, NULL, "Received packet, resetting win wake"); @@ -172,7 +182,10 @@ void PowerFSM_setup() powerFSM.add_transition(&stateLS, &stateON, EVENT_PRESS, NULL, "Press"); powerFSM.add_transition(&stateNB, &stateON, EVENT_PRESS, NULL, "Press"); powerFSM.add_transition(&stateDARK, &stateON, EVENT_PRESS, NULL, "Press"); + powerFSM.add_transition(&statePOWER, &statePOWER, EVENT_PRESS, screenPress, "Press"); powerFSM.add_transition(&stateON, &stateON, EVENT_PRESS, screenPress, "Press"); // reenter On to restart our timers + powerFSM.add_transition(&stateSERIAL, &stateSERIAL, EVENT_PRESS, screenPress, + "Press"); // Allow button to work while in serial API // Handle critically low power battery by forcing deep sleep powerFSM.add_transition(&stateBOOT, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); @@ -199,6 +212,14 @@ void PowerFSM_setup() powerFSM.add_transition(&stateDARK, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "serial API"); powerFSM.add_transition(&stateON, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "serial API"); + powerFSM.add_transition(&stateLS, &statePOWER, EVENT_POWER_CONNECTED, NULL, "power connect"); + 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, &stateON, EVENT_POWER_DISCONNECTED, NULL, "power disconnected"); + powerFSM.add_transition(&stateSERIAL, &stateON, EVENT_POWER_DISCONNECTED, NULL, "power disconnected"); + powerFSM.add_transition(&stateSERIAL, &stateNB, EVENT_SERIAL_DISCONNECTED, NULL, "serial disconnect"); powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_CONTACT_FROM_PHONE, NULL, "Contact from phone"); diff --git a/src/PowerFSM.h b/src/PowerFSM.h index c89ad9148..4a219f570 100644 --- a/src/PowerFSM.h +++ b/src/PowerFSM.h @@ -13,9 +13,11 @@ #define EVENT_BLUETOOTH_PAIR 7 #define EVENT_NODEDB_UPDATED 8 // NodeDB has a big enough change that we think you should turn on the screen #define EVENT_CONTACT_FROM_PHONE 9 // the phone just talked to us over bluetooth -#define EVENT_LOW_BATTERY 10 // Battery is critically low, go to sleep +#define EVENT_LOW_BATTERY 10 // Battery is critically low, go to sleep #define EVENT_SERIAL_CONNECTED 11 #define EVENT_SERIAL_DISCONNECTED 12 +#define EVENT_POWER_CONNECTED 13 +#define EVENT_POWER_DISCONNECTED 14 extern Fsm powerFSM; diff --git a/src/SerialConsole.cpp b/src/SerialConsole.cpp index 683886ed5..f246b607c 100644 --- a/src/SerialConsole.cpp +++ b/src/SerialConsole.cpp @@ -40,6 +40,8 @@ void SerialConsole::onConnectionChanged(bool connected) if (connected) { // To prevent user confusion, turn off bluetooth while using the serial port api powerFSM.trigger(EVENT_SERIAL_CONNECTED); } else { + // FIXME, we get no notice of serial going away, we should instead automatically generate this event if we haven't + // received a packet in a while powerFSM.trigger(EVENT_SERIAL_DISCONNECTED); } } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 207ae7b12..dc188809d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -213,9 +213,9 @@ void setup() // Currently only the tbeam has a PMU power = new Power(); - power->setup(); power->setStatusHandler(powerStatus); powerStatus->observe(&power->newStatus); + power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration #ifdef NRF52_SERIES nrf52Setup(); From 10b24c02696877a7f60156b5856e76d9e95821de Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Tue, 22 Sep 2020 21:01:31 -0700 Subject: [PATCH 24/34] Initial check-in of David's UI --- src/meshwifi/meshhttp.cpp | 433 ++++++++++++++++++++++++++++++----- src/meshwifi/meshhttp.h | 3 + src/meshwifi/meshwifi.cpp | 2 +- src/nimble/BluetoothUtil.cpp | 8 + 4 files changed, 387 insertions(+), 59 deletions(-) diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index 6b3776730..b8915df3f 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -8,6 +8,8 @@ WebServer webserver(80); +// 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; struct message_t { @@ -19,9 +21,8 @@ struct message_t { bool fromMe; }; -struct messages_t -{ - message_t history[maxMessages]; // 900 positions to save up to 1200 seconds (15 minutes). uInt for each temerature sensor, Input and Setpoint. +struct messages_t { + message_t history[maxMessages]; }; messages_t messages_history; @@ -51,6 +52,7 @@ void initWebServer() 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("/", handleRoot); webserver.begin(); } @@ -123,61 +125,6 @@ void handleHotspot() return; } -void handleRoot() -{ - DEBUG_MSG("Hotspot Request\n"); - - /* - If we don't do a redirect, be sure to return a "Success" message - otherwise iOS will have trouble detecting that the connection to the SoftAP worked. - */ - - String out = ""; - // out += "Success\n"; - out += "\n" - "\n" - "\n" - "\n" - "Meshtastic - WebUI\n" - "\n" - "\n" - "\n" - "
\n" - "
\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - "
Meshtastic - WebUI (Pre-Alpha)
\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - "
Channels:
\n" - "
\n" - " #general
\n" - " #stuff
\n" - " #things
\n" - "
Everything is awesome!
\n" - "
\n" - "
\n" - "
\n" - "\n" - "\n"; - webserver.send(200, "text/html", out); - return; -} - void notifyWebUI() { DEBUG_MSG("************ Got a message! ************\n"); @@ -190,4 +137,374 @@ void notifyWebUI() snprintf(tempBuf, sizeof(tempBuf), "%s", mp.decoded.data.payload.bytes); something = tempBuf; +} + +//---------------------------------------- + +void handleRoot() +{ + + String out = ""; + out += " < !DOCTYPE html >\n" + "\n" + "\n" + " \n" + " Meshtastic - Chat\n" + " \n" + "\n" + "\n" + "\n" + "
\n" + "\t
\n" + "\t\t
Meshtastic - Chat
\n" + "\t
\n" + "\n" + "\t
\n" + "
\n" + "\t
\n" + "\t\t
Channels
\n" + "\t
\n" + "
    \n" + "
  • \n" + "
    HotChannel
    \n" + "
    \n" + "\t\t 28 messages\n" + "
    \n" + "
  • \n" + "\t\t
  • \n" + "
    AnotherChannel
    \n" + "
    \n" + "\t\t 12 messages\n" + "
    \n" + "
  • \n" + "\t\t
  • \n" + "
    Lost
    \n" + "
    \n" + "\t\t 6 messages\n" + "
    \n" + "
  • \n" + "
\n" + "
\n" + "
\n" + "
\n" + "
\n" + "\n" + "
Chat from: \n" + "\t\t HotChannel\n" + "\t\t
\n" + "\n" + "
\n" + " \n" + "
\n" + "
    \n" + "
  • \n" + "
    \n" + " 10:10 AM, Today    \n" + " Olia \n" + " \n" + "
    \n" + "
    \n" + " Hi Vincent, how are you? How is the project coming along?\n" + "
    \n" + "
  • \n" + " \n" + "
  • \n" + "
    \n" + " Vincent\n" + " 10:12 AM, Today\n" + "
    \n" + "
    \n" + " Are we meeting today? Project has been already finished and I have results to show you.\n" + "
    \n" + "
  • \n" + " \n" + "
  • \n" + "
    \n" + " 10:14 AM, Today    \n" + " Olia \n" + " \n" + "
    \n" + "
    \n" + " Well I am not sure. The rest of the team is not here yet. Maybe in an hour or so? Have you faced any " + "problems at the last phase of the project?\n" + "
    \n" + "
  • \n" + " \n" + "
  • \n" + "
    \n" + " Vincent\n" + " 10:20 AM, Today\n" + "
    \n" + "
    \n" + " Actually everything was fine. I'm very excited to show this to our team.\n" + "
    \n" + "
  • \n" + " \n" + " \n" + "
\n" + " \n" + "
\n" + " \n" + "
\n" + " \n" + " \n" + " \n" + " \n" + "\n" + "
\n" + " \n" + "
\n" + " \n" + "
\n" + "\n" + "\n" + "\n" + ""; + webserver.send(200, "text/html", out); + return; +} + +void handleStyleCSS() +{ + + String out = ""; + out += + "/* latin-ext */\n" + "@font-face {\n" + " font-family: 'Lato';\n" + " font-style: normal;\n" + " font-weight: 400;\n" + " src: local('Lato Regular'), local('Lato-Regular'), url(./Google.woff2) format('woff2');\n" + " unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;\n" + "}\n" + "\n" + "*, *:before, *:after {\n" + " box-sizing: border-box;\n" + "}\n" + "\n" + "body {\n" + " background: #C5DDEB;\n" + " font: 14px/20px \"Lato\", Arial, sans-serif;\n" + " padding: 40px 0;\n" + " color: white;\n" + "}\n" + "\n" + "\n" + " \n" + ".grid {\n" + " display: grid;\n" + " grid-template-columns:\n" + "\t1fr 4fr;\n" + " grid-template-areas:\n" + "\t\"header header\"\n" + "\t\"sidebar content\";\n" + " margin: 0 auto;\n" + " width: 750px;\n" + " background: #444753;\n" + " border-radius: 5px;\n" + "}\n" + "\n" + ".top {grid-area: header;}\n" + ".side {grid-area: sidebar;}\n" + ".main {grid-area: content;}\n" + "\n" + ".top {\n" + " border-bottom: 2px solid white;\n" + "}\n" + ".top-text {\n" + " font-weight: bold;\n" + " font-size: 24px;\n" + " text-align: center;\n" + " padding: 20px;\n" + "}\n" + "\n" + ".side {\n" + " width: 260px;\n" + " float: left;\n" + "}\n" + ".side .side-header {\n" + " padding: 20px;\n" + " border-bottom: 2px solid white;\n" + "}\n" + "\n" + ".side .side-header .side-text {\n" + " padding-left: 10px;\n" + " margin-top: 6px;\n" + " font-size: 16px;\n" + " text-align: left;\n" + " font-weight: bold;\n" + " \n" + "}\n" + "\n" + ".channel-list ul {\n" + " padding: 20px;\n" + " height: 570px;\n" + " list-style-type: none;\n" + "}\n" + ".channel-list ul li {\n" + " padding-bottom: 20px;\n" + "}\n" + "\n" + ".channel-list .channel-name {\n" + " font-size: 20px;\n" + " margin-top: 8px;\n" + " padding-left: 8px;\n" + "}\n" + "\n" + ".channel-list .message-count {\n" + " padding-left: 16px;\n" + " color: #92959E;\n" + "}\n" + "\n" + ".content {\n" + " display: flex;\n" + " flex-direction: column;\n" + " flex-wrap: nowrap;\n" + "/* width: 490px; */\n" + " float: left;\n" + " background: #F2F5F8;\n" + "/* border-top-right-radius: 5px;\n" + " border-bottom-right-radius: 5px; */\n" + " color: #434651;\n" + "}\n" + ".content .content-header {\n" + " flex-grow: 0;\n" + " padding: 20px;\n" + " border-bottom: 2px solid white;\n" + "}\n" + "\n" + ".content .content-header .content-from {\n" + " padding-left: 10px;\n" + " margin-top: 6px;\n" + " font-size: 20px;\n" + " text-align: center;\n" + " font-size: 16px;\n" + "}\n" + ".content .content-header .content-from .selected-channel {\n" + " font-weight: bold;\n" + "}\n" + ".content .content-header .content-num-messages {\n" + " color: #92959E;\n" + "}\n" + "\n" + ".content .content-history {\n" + " flex-grow: 1;\n" + " padding: 20px 20px 20px;\n" + " border-bottom: 2px solid white;\n" + " overflow-y: scroll;\n" + " height: 375px;\n" + "}\n" + ".content .content-history ul {\n" + " list-style-type: none;\n" + " padding-inline-start: 10px;\n" + "}\n" + ".content .content-history .message-data {\n" + " margin-bottom: 10px;\n" + "}\n" + ".content .content-history .message-data-time {\n" + " color: #a8aab1;\n" + " padding-left: 6px;\n" + "}\n" + ".content .content-history .message {\n" + " color: white;\n" + " padding: 8px 10px;\n" + " line-height: 20px;\n" + " font-size: 14px;\n" + " border-radius: 7px;\n" + " margin-bottom: 30px;\n" + " width: 90%;\n" + " position: relative;\n" + "}\n" + ".content .content-history .message:after {\n" + " bottom: 100%;\n" + " left: 7%;\n" + " border: solid transparent;\n" + " content: \" \";\n" + " height: 0;\n" + " width: 0;\n" + " position: absolute;\n" + " pointer-events: none;\n" + " border-bottom-color: #86BB71;\n" + " border-width: 10px;\n" + " margin-left: -10px;\n" + "}\n" + ".content .content-history .my-message {\n" + " background: #86BB71;\n" + "}\n" + ".content .content-history .other-message {\n" + " background: #94C2ED;\n" + "}\n" + ".content .content-history .other-message:after {\n" + " border-bottom-color: #94C2ED;\n" + " left: 93%;\n" + "}\n" + ".content .content-message {\n" + " flex-grow: 0;\n" + " padding: 10px;\n" + "}\n" + ".content .content-message textarea {\n" + " width: 100%;\n" + " border: none;\n" + " padding: 10px 10px;\n" + " font: 14px/22px \"Lato\", Arial, sans-serif;\n" + " margin-bottom: 10px;\n" + " border-radius: 5px;\n" + " resize: none;\n" + "}\n" + "\n" + ".content .content-message button {\n" + " float: right;\n" + " color: #94C2ED;\n" + " font-size: 16px;\n" + " text-transform: uppercase;\n" + " border: none;\n" + " cursor: pointer;\n" + " font-weight: bold;\n" + " background: #F2F5F8;\n" + "}\n" + ".content .content-message button:hover {\n" + " color: #75b1e8;\n" + "}\n" + "\n" + ".online, .offline, .me {\n" + " margin-right: 3px;\n" + " font-size: 10px;\n" + "}\n" + "\n" + ".online {\n" + " color: #86BB71;\n" + "}\n" + "\n" + ".offline {\n" + " color: #E38968;\n" + "}\n" + "\n" + ".me {\n" + " color: #94C2ED;\n" + "}\n" + "\n" + ".align-left {\n" + " text-align: left;\n" + "}\n" + "\n" + ".align-right {\n" + " text-align: right;\n" + "}\n" + "\n" + ".float-right {\n" + " float: right;\n" + "}\n" + "\n" + ".clearfix:after {\n" + " visibility: hidden;\n" + " display: block;\n" + " font-size: 0;\n" + " content: \" \";\n" + " clear: both;\n" + " height: 0;\n" + "}"; + + webserver.send(200, "text/html", out); + return; } \ No newline at end of file diff --git a/src/meshwifi/meshhttp.h b/src/meshwifi/meshhttp.h index b1a5dbb94..d959fe11f 100644 --- a/src/meshwifi/meshhttp.h +++ b/src/meshwifi/meshhttp.h @@ -15,4 +15,7 @@ void notifyWebUI(); void handleHotspot(); +// WebServer webserver(80); + +void handleStyleCSS(); void handleRoot(); \ No newline at end of file diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index ad8a88fa2..84a9a5a57 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -91,7 +91,7 @@ void initWifi() WiFiEventId_t eventID = WiFi.onEvent( [](WiFiEvent_t event, WiFiEventInfo_t info) { - Serial.print("\n-------------- WiFi lost connection. Reason: "); + Serial.print("\nWiFi lost connection. Reason: "); Serial.println(info.disconnected.reason); // wifiDisconnectReason = info.disconnected.reason; }, diff --git a/src/nimble/BluetoothUtil.cpp b/src/nimble/BluetoothUtil.cpp index de9f0c611..f294802cd 100644 --- a/src/nimble/BluetoothUtil.cpp +++ b/src/nimble/BluetoothUtil.cpp @@ -526,6 +526,14 @@ void setBluetoothEnable(bool on) initWifi(); } } else { + + /* + // If WiFi is in use, disable shutting down the radio. + if (isWifiAvailable()) { + return; + } + */ + // shutdown wifi deinitWifi(); From 9c0a0ad22083f0371f27aa7e090ce5e56c30a037 Mon Sep 17 00:00:00 2001 From: geeksville Date: Wed, 23 Sep 2020 17:22:17 -0700 Subject: [PATCH 25/34] Add stubs so that portduino can build with wifi. cc @mc-hamster --- platformio.ini | 2 +- src/nrf52/{wifi-nrf52.cpp => wifi-stubs.cpp} | 0 src/portduino/wifi-stubs.cpp | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) rename src/nrf52/{wifi-nrf52.cpp => wifi-stubs.cpp} (100%) create mode 120000 src/portduino/wifi-stubs.cpp diff --git a/platformio.ini b/platformio.ini index 3ab4a7815..4ed9e967a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -253,7 +253,7 @@ lib_deps = ; The Portduino based sim environment on top of linux [env:linux] platform = https://github.com/geeksville/platform-portduino.git -src_filter = ${env.src_filter} - - - +src_filter = ${env.src_filter} - - - - build_flags = ${arduino_base.build_flags} -O0 framework = arduino board = linux_x86_64 diff --git a/src/nrf52/wifi-nrf52.cpp b/src/nrf52/wifi-stubs.cpp similarity index 100% rename from src/nrf52/wifi-nrf52.cpp rename to src/nrf52/wifi-stubs.cpp diff --git a/src/portduino/wifi-stubs.cpp b/src/portduino/wifi-stubs.cpp new file mode 120000 index 000000000..b90e66295 --- /dev/null +++ b/src/portduino/wifi-stubs.cpp @@ -0,0 +1 @@ +../nrf52/wifi-stubs.cpp \ No newline at end of file From ce7fa65595f86a27a2a63396cdd6dcb34bc86d77 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Wed, 23 Sep 2020 19:04:12 -0700 Subject: [PATCH 26/34] David's latest changes to the HTML UI --- src/meshwifi/meshhttp.cpp | 523 +++++++++++++++++++++++++++++--------- src/meshwifi/meshhttp.h | 5 +- 2 files changed, 406 insertions(+), 122 deletions(-) diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index b8915df3f..959460c58 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -22,7 +22,7 @@ struct message_t { }; struct messages_t { - message_t history[maxMessages]; + message_t history[maxMessages]; }; messages_t messages_history; @@ -49,10 +49,12 @@ void initWebServer() 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(); } @@ -139,128 +141,88 @@ void notifyWebUI() something = tempBuf; } -//---------------------------------------- +/* + To convert text to c strings: + https://tomeko.net/online_tools/cpp_text_escape.php?lang=en +*/ void handleRoot() { String out = ""; - out += " < !DOCTYPE html >\n" - "\n" - "\n" - " \n" - " Meshtastic - Chat\n" - " \n" - "\n" - "\n" - "\n" - "
\n" - "\t
\n" - "\t\t
Meshtastic - Chat
\n" - "\t
\n" - "\n" - "\t
\n" - "
\n" - "\t
\n" - "\t\t
Channels
\n" - "\t
\n" - "
    \n" - "
  • \n" - "
    HotChannel
    \n" - "
    \n" - "\t\t 28 messages\n" - "
    \n" - "
  • \n" - "\t\t
  • \n" - "
    AnotherChannel
    \n" - "
    \n" - "\t\t 12 messages\n" - "
    \n" - "
  • \n" - "\t\t
  • \n" - "
    Lost
    \n" - "
    \n" - "\t\t 6 messages\n" - "
    \n" - "
  • \n" - "
\n" - "
\n" - "
\n" - "
\n" - "
\n" - "\n" - "
Chat from: \n" - "\t\t HotChannel\n" - "\t\t
\n" - "\n" - "
\n" - " \n" - "
\n" - "
    \n" - "
  • \n" - "
    \n" - " 10:10 AM, Today    \n" - " Olia \n" - " \n" - "
    \n" - "
    \n" - " Hi Vincent, how are you? How is the project coming along?\n" - "
    \n" - "
  • \n" - " \n" - "
  • \n" - "
    \n" - " Vincent\n" - " 10:12 AM, Today\n" - "
    \n" - "
    \n" - " Are we meeting today? Project has been already finished and I have results to show you.\n" - "
    \n" - "
  • \n" - " \n" - "
  • \n" - "
    \n" - " 10:14 AM, Today    \n" - " Olia \n" - " \n" - "
    \n" - "
    \n" - " Well I am not sure. The rest of the team is not here yet. Maybe in an hour or so? Have you faced any " - "problems at the last phase of the project?\n" - "
    \n" - "
  • \n" - " \n" - "
  • \n" - "
    \n" - " Vincent\n" - " 10:20 AM, Today\n" - "
    \n" - "
    \n" - " Actually everything was fine. I'm very excited to show this to our team.\n" - "
    \n" - "
  • \n" - " \n" - " \n" - "
\n" - " \n" - "
\n" - " \n" - "
\n" - " \n" - " \n" - " \n" - " \n" - "\n" - "
\n" - " \n" - "
\n" - " \n" - "
\n" - "\n" - "\n" - "\n" - ""; + out += + "\n" + "\n" + "\n" + "\n" + "\n" + " \n" + " Meshtastic - Chat\n" + " \n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "
\n" + "\t
\n" + "\t\t
Meshtastic - Chat
\n" + "\t
\n" + "\n" + "\t
\n" + "
\n" + "\t
\n" + "\t\t
Users
\n" + "\t
\n" + "
    \n" + "
\n" + "
\n" + "
\n" + "
\n" + "
\n" + "\n" + "
\n" + "\t\t All Users\n" + "\t\t
\n" + "\n" + "
\n" + " \n" + "
\n" + "
    \n" + "\t\t
\n" + " \n" + "
\n" + " \n" + "
\n" + " \n" + " \n" + " \n" + " \n" + "\n" + "
\n" + " \n" + "
\n" + " \n" + "
\n" + "\n" + "\n" + "\n" + "\n" + "\n" + ""; webserver.send(200, "text/html", out); return; } @@ -279,6 +241,7 @@ void handleStyleCSS() " unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;\n" "}\n" "\n" + "\n" "*, *:before, *:after {\n" " box-sizing: border-box;\n" "}\n" @@ -357,6 +320,23 @@ void handleStyleCSS() " color: #92959E;\n" "}\n" "\n" + ".icon {\n" + " display: inline-block;\n" + " width: 1em;\n" + " height: 1em;\n" + " stroke-width: 0;\n" + " stroke: currentColor;\n" + " fill: currentColor;\n" + "}\n" + "\n" + ".icon-map-marker {\n" + " width: 0.5714285714285714em;\n" + "}\n" + "\n" + ".icon-circle {\n" + " width: 0.8571428571428571em;\n" + "}\n" + "\n" ".content {\n" " display: flex;\n" " flex-direction: column;\n" @@ -381,7 +361,7 @@ void handleStyleCSS() " text-align: center;\n" " font-size: 16px;\n" "}\n" - ".content .content-header .content-from .selected-channel {\n" + ".content .content-header .content-from .content-from-highlight {\n" " font-weight: bold;\n" "}\n" ".content .content-header .content-num-messages {\n" @@ -466,6 +446,31 @@ void handleStyleCSS() ".content .content-message button:hover {\n" " color: #75b1e8;\n" "}\n" + "/* Tooltip container */\n" + ".tooltip {\n" + " color: #86BB71;\n" + " position: relative;\n" + " display: inline-block;\n" + " border-bottom: 1px dotted black; /* If you want dots under the hoverable text */\n" + "}\n" + "/* Tooltip text */\n" + ".tooltip .tooltiptext {\n" + " visibility: hidden;\n" + " width: 120px;\n" + " background-color: #444753;\n" + " color: #fff;\n" + " text-align: center;\n" + " padding: 5px 0;\n" + " border-radius: 6px;\n" + " /* Position the tooltip text - see examples below! */\n" + " position: absolute;\n" + " z-index: 1;\n" + "}\n" + "\n" + "/* Show the tooltip text when you mouse over the tooltip container */\n" + ".tooltip:hover .tooltiptext {\n" + " visibility: visible;\n" + "}\n" "\n" ".online, .offline, .me {\n" " margin-right: 3px;\n" @@ -505,6 +510,284 @@ void handleStyleCSS() " height: 0;\n" "}"; - webserver.send(200, "text/html", out); + webserver.send(200, "text/css", out); + return; +} + +void handleScriptsScriptJS() +{ + String out = ""; + out += "String.prototype.toHHMMSS = function () {\n" + " var sec_num = parseInt(this, 10); // don't forget the second param\n" + " var hours = Math.floor(sec_num / 3600);\n" + " var minutes = Math.floor((sec_num - (hours * 3600)) / 60);\n" + " var seconds = sec_num - (hours * 3600) - (minutes * 60);\n" + "\n" + " if (hours < 10) {hours = \"0\"+hours;}\n" + " if (minutes < 10) {minutes = \"0\"+minutes;}\n" + " if (seconds < 10) {seconds = \"0\"+seconds;}\n" + "// return hours+':'+minutes+':'+seconds;\n" + "\treturn hours+'h'+minutes+'m';\n" + "}\n" + "String.prototype.padLeft = function (length, character) { \n" + " return new Array(length - this.length + 1).join(character || ' ') + this; \n" + "};\n" + "\n" + "Date.prototype.toFormattedString = function () {\n" + " return [String(this.getFullYear()).substr(2, 2),\n" + "\t\t\tString(this.getMonth()+1).padLeft(2, '0'),\n" + " String(this.getDate()).padLeft(2, '0')].join(\"/\") + \" \" +\n" + " [String(this.getHours()).padLeft(2, '0'),\n" + " String(this.getMinutes()).padLeft(2, '0')].join(\":\");\n" + "};\n" + "\n" + "function getData(file) {\n" + "\tfetch(file)\n" + "\t.then(function (response) {\n" + "\t\treturn response.json();\n" + "\t})\n" + "\t.then(function (datafile) {\n" + "\t\tupdateData(datafile);\n" + "\t})\n" + "\t.catch(function (err) {\n" + "\t\tconsole.log('error: ' + err);\n" + "\t});\n" + "}\n" + "\t\n" + "function updateData(datafile) {\n" + "// Update System Details\n" + "\tupdateSystem(datafile);\n" + "//\tUpdate Userlist and message count\n" + "\tupdateUsers(datafile);\n" + "// Update Chat\n" + "\tupdateChat(datafile);\n" + "}\n" + "\n" + "function updateSystem(datafile) {\n" + "// Update System Info \n" + "\tvar sysContainer = document.getElementById(\"content-from-id\");\n" + "\tvar newHTML = datafile.data.system.channel;\n" + "\tvar myDate = new Date( datafile.data.system.timeGPS *1000);\n" + "\tnewHTML += ' @' + myDate.toFormattedString();\n" + "\tvar newSec = datafile.data.system.timeSinceStart;\n" + "\tvar strsecondUp = newSec.toString();\n" + "\tnewHTML += ' Up:' + strsecondUp.toHHMMSS();\n" + "\tsysContainer.innerHTML = newHTML;\n" + "}\n" + "\n" + "function updateUsers(datafile) {\n" + "\tvar mainContainer = document.getElementById(\"userlist-id\");\n" + "\tvar htmlUsers = '';\n" + "\tvar timeBase = datafile.data.system.timeSinceStart;\n" + "//\tvar lookup = {};\n" + " for (var i = 0; i < datafile.data.users.length; i++) {\n" + " htmlUsers += formatUsers(datafile.data.users[i],timeBase);\n" + "\t}\n" + "\tmainContainer.innerHTML = htmlUsers;\n" + "}\n" + "\n" + "function formatUsers(user,timeBase) {\n" + "\tnewHTML = '
  • ';\n" + " newHTML += '
    ' + user.NameLong + '(' + user.NameShort + ')
    ';\n" + " newHTML += '
    ';\n" + "\tvar secondsLS = timeBase - user.lastSeen;\n" + "\tvar strsecondsLS = secondsLS.toString();\n" + "\tnewHTML += 'Seen: '+strsecondsLS.toHHMMSS()+' ago ';\n" + "\tif (user.lat == 0 || user.lon == 0) {\n" + "\t\tnewHTML += '';\n" + "\t} else {\n" + "\t\tnewHTML += '
    lat:' + user.lat + ' lon:'+ user.lon+ " + "'';\n" + "\t}\n" + " newHTML += '
    ';\n" + " newHTML += '
  • ';\n" + "\treturn(newHTML);\n" + "}\n" + "\n" + "function onlineStatus(time) {\n" + "\tif (time < 3600) {\n" + "\t\treturn \"online\"\n" + "\t} else {\n" + "\t\treturn \"offline\"\n" + "\t}\n" + "}\n" + "\n" + "function updateChat(datafile) {\n" + "// Update Chat\n" + "\tvar chatContainer = document.getElementById(\"chat-history-id\");\n" + "\tvar htmlChat = '';\n" + "\tvar timeBase = datafile.data.system.timeSinceStart;\n" + "\tfor (var i = 0; i < datafile.data.chat.length; i++) {\n" + "\t\thtmlChat += formatChat(datafile.data.chat[i],timeBase);\n" + "\t}\n" + "\tchatContainer.innerHTML = htmlChat;\n" + "\tscrollHistory();\n" + "}\n" + "\n" + "function formatChat(data,timeBase) {\n" + "\tvar secondsTS = timeBase - data.timestamp;\n" + "\tvar strsecondsTS = secondsTS.toString();\n" + "\tnewHTML = '
  • ';\n" + "\tif (data.local == 1) {\n" + "\t\tnewHTML += '
    ';\n" + "\t\tnewHTML += '' + data.NameLong + '(' + data.NameShort + ')';\n" + "\t\tnewHTML += '' + strsecondsTS.toHHMMSS() + ' ago';\n" + "\t\tnewHTML += '
    ';\n" + "\t\tnewHTML += '
    ' + data.chatLine + '
    ';\n" + "\t} else {\n" + "\t\tnewHTML += '
    ';\n" + "\t\tnewHTML += '' + strsecondsTS.toHHMMSS() + ' ago    ';\n" + "\t\tnewHTML += '' + data.NameLong + '(' + data.NameShort + ')';\n" + "//\t\tnewHTML += '';\n" + "\t\tnewHTML += '
    ';\n" + "\t\tnewHTML += '
    ' + data.chatLine + '
    ';\n" + "\t}\n" + "\n" + " newHTML += '
  • ';\n" + "\treturn(newHTML);\t\n" + "}\n" + "\n" + "function scrollHistory() {\n" + "\tvar chatContainer = document.getElementById(\"chat-div-id\");\n" + "\tchatContainer.scrollTop = chatContainer.scrollHeight;\n" + "}\n" + "\n" + "\n" + "getData('/json/chat/history/dummy');\n" + "\n" + "\n" + "//window.onload=function(){\n" + "//\talert('onload');\n" + "// Async - Run scroll 0.5sec after onload event\n" + "//\tsetTimeout(scrollHistory(),500);\n" + "// }"; + + webserver.send(200, "text/javascript", out); + return; +} + +void handleJSONChatHistoryDummy() +{ + String out = ""; + out += "{\n" + "\t\"data\": {\n" + "\t\t\"system\": {\n" + "\t\t\t\"timeSinceStart\": 3213544,\n" + "\t\t\t\"timeGPS\": 1600830985,\n" + "\t\t\t\"channel\": \"ourSecretPlace\"\n" + "\t\t},\n" + "\t\t\"users\": [{\n" + "\t\t\t\t\"NameShort\": \"J\",\n" + "\t\t\t\t\"NameLong\": \"John\",\n" + "\t\t\t\t\"lastSeen\": 3207544,\n" + "\t\t\t\t\"lat\" : -2.882243,\n" + "\t\t\t\t\"lon\" : -111.038580\n" + "\t\t\t},\n" + "\t\t\t{\n" + "\t\t\t\t\"NameShort\": \"D\",\n" + "\t\t\t\t\"NameLong\": \"David\",\n" + "\t\t\t\t\"lastSeen\": 3212544,\n" + "\t\t\t\t\"lat\" : -12.24452,\n" + "\t\t\t\t\"lon\" : -61.87351\n" + "\t\t\t},\n" + "\t\t\t{\n" + "\t\t\t\t\"NameShort\": \"P\",\n" + "\t\t\t\t\"NameLong\": \"Peter\",\n" + "\t\t\t\t\"lastSeen\": 3213444,\n" + "\t\t\t\t\"lat\" : 0,\n" + "\t\t\t\t\"lon\" : 0\n" + "\t\t\t},\n" + "\t\t\t{\n" + "\t\t\t\t\"NameShort\": \"M\",\n" + "\t\t\t\t\"NameLong\": \"Mary\",\n" + "\t\t\t\t\"lastSeen\": 3211544,\n" + "\t\t\t\t\"lat\" : 16.45478,\n" + "\t\t\t\t\"lon\" : 11.40166\n" + "\t\t\t}\n" + "\t\t],\n" + "\t\t\"chat\": [{\n" + "\t\t\t\t\"local\": 0,\n" + "\t\t\t\t\"NameShort\": \"J\",\n" + "\t\t\t\t\"NameLong\": \"John\",\n" + "\t\t\t\t\"chatLine\": \"Hello\",\n" + "\t\t\t\t\"timestamp\" : 3203544\n" + "\t\t\t},\n" + "\t\t\t{\n" + "\t\t\t\t\"local\": 0,\n" + "\t\t\t\t\"NameShort\": \"D\",\n" + "\t\t\t\t\"NameLong\": \"David\",\n" + "\t\t\t\t\"chatLine\": \"Hello There\",\n" + "\t\t\t\t\"timestamp\" : 3204544\n" + "\t\t\t},\n" + "\t\t\t{\n" + "\t\t\t\t\"local\": 0,\n" + "\t\t\t\t\"NameShort\": \"J\",\n" + "\t\t\t\t\"NameLong\": \"John\",\n" + "\t\t\t\t\"chatLine\": \"Where you been?\",\n" + "\t\t\t\t\"timestamp\" : 3205544\n" + "\t\t\t},\n" + "\t\t\t{\n" + "\t\t\t\t\"local\": 0,\n" + "\t\t\t\t\"NameShort\": \"D\",\n" + "\t\t\t\t\"NameLong\": \"David\",\n" + "\t\t\t\t\"chatLine\": \"I was on Channel 2\",\n" + "\t\t\t\t\"timestamp\" : 3206544\n" + "\t\t\t},\n" + "\t\t\t{\n" + "\t\t\t\t\"local\": 0,\n" + "\t\t\t\t\"NameShort\": \"J\",\n" + "\t\t\t\t\"NameLong\": \"John\",\n" + "\t\t\t\t\"chatLine\": \"With Mary again?\",\n" + "\t\t\t\t\"timestamp\" : 3207544\n" + "\t\t\t},\n" + "\t\t\t{\n" + "\t\t\t\t\"local\": 0,\n" + "\t\t\t\t\"NameShort\": \"D\",\n" + "\t\t\t\t\"NameLong\": \"David\",\n" + "\t\t\t\t\"chatLine\": \"She's better looking than you\",\n" + "\t\t\t\t\"timestamp\" : 3208544\n" + "\t\t\t},\n" + "\t\t\t{\n" + "\t\t\t\t\"local\": 0,\n" + "\t\t\t\t\"NameShort\": \"M\",\n" + "\t\t\t\t\"NameLong\": \"Mary\",\n" + "\t\t\t\t\"chatLine\": \"Well, Hi\",\n" + "\t\t\t\t\"timestamp\" : 3209544\n" + "\t\t\t},\n" + "\t\t\t{\n" + "\t\t\t\t\"local\": 0,\n" + "\t\t\t\t\"NameShort\": \"D\",\n" + "\t\t\t\t\"NameLong\": \"David\",\n" + "\t\t\t\t\"chatLine\": \"You're Here\",\n" + "\t\t\t\t\"timestamp\" : 3210544\n" + "\t\t\t},\n" + "\t\t\t{\n" + "\t\t\t\t\"local\": 0,\n" + "\t\t\t\t\"NameShort\": \"M\",\n" + "\t\t\t\t\"NameLong\": \"Mary\",\n" + "\t\t\t\t\"chatLine\": \"Wanted to say Howdy.\",\n" + "\t\t\t\t\"timestamp\" : 3211544\n" + "\t\t\t},\n" + "\t\t\t{\n" + "\t\t\t\t\"local\": 0,\n" + "\t\t\t\t\"NameShort\": \"D\",\n" + "\t\t\t\t\"NameLong\": \"David\",\n" + "\t\t\t\t\"chatLine\": \"Better come down and visit sometime\",\n" + "\t\t\t\t\"timestamp\" : 3212544\n" + "\t\t\t},\n" + "\t\t\t{\n" + "\t\t\t\t\"local\": 1,\n" + "\t\t\t\t\"NameShort\": \"P\",\n" + "\t\t\t\t\"NameLong\": \"Peter\",\n" + "\t\t\t\t\"chatLine\": \"Where is everybody?\",\n" + "\t\t\t\t\"timestamp\" : 3213444\n" + "\t\t\t}\n" + "\t\t]\n" + "\t}\n" + "}"; + + webserver.send(200, "application/json", out); return; } \ No newline at end of file diff --git a/src/meshwifi/meshhttp.h b/src/meshwifi/meshhttp.h index d959fe11f..42c6644bf 100644 --- a/src/meshwifi/meshhttp.h +++ b/src/meshwifi/meshhttp.h @@ -15,7 +15,8 @@ void notifyWebUI(); void handleHotspot(); -// WebServer webserver(80); void handleStyleCSS(); -void handleRoot(); \ No newline at end of file +void handleRoot(); +void handleScriptsScriptJS(); +void handleJSONChatHistoryDummy(); \ No newline at end of file From d3c00584a232a86db20d7a313f96c5057dbb16fb Mon Sep 17 00:00:00 2001 From: geeksville Date: Thu, 24 Sep 2020 10:36:37 -0700 Subject: [PATCH 27/34] oops - the NRF52 build rules are suppose to inherit from arduino_base. --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 4ed9e967a..fb6508e70 100644 --- a/platformio.ini +++ b/platformio.ini @@ -172,7 +172,7 @@ build_flags = -Isdk-nrfxlib/crypto/nrf_oberon/include -Lsdk-nrfxlib/crypto/nrf_oberon/lib/cortex-m4/hard-float/ -lliboberon_3.0.3 ;-DCFG_DEBUG=3 src_filter = - ${env.src_filter} - - - + ${arduino_base.src_filter} - - - lib_ignore = BluetoothOTA monitor_port = /dev/ttyACM1 From 0d3b8bdb22483eafb7be884cc1d23ed04fb74b9b Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Thu, 24 Sep 2020 11:07:30 -0700 Subject: [PATCH 28/34] Note not to file bugs --- src/meshwifi/meshhttp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index 959460c58..9106ab08b 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -162,7 +162,7 @@ void handleRoot() "\n" "\n" "\n" - "\n" + "

    This area is under development. Please don't file bugs.

    \n" "\n" "\n" From 1f36139e996a707e3c5ed084a3ac5551dfc77cea Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 25 Sep 2020 09:14:44 -0700 Subject: [PATCH 29/34] remove Signal --- docs/_config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_config.yml b/docs/_config.yml index 9c1ecd436..1cb1a55ba 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,7 +1,7 @@ theme: jekyll-theme-cayman title: Meshtastic -description: An opensource hiking, pilot, skiing, Signal-App-extending GPS mesh communicator +description: An opensource hiking, pilot, skiing, secure GPS mesh communicator google_analytics: G-DRZ5H5EXHV include: [".well-known"] From 3e5f81bf2abb594ac6b9bb3a4ea0f517ca127c10 Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 25 Sep 2020 12:52:08 -0700 Subject: [PATCH 30/34] move region into userpreferences, to end region specific firmwares --- .vscode/settings.json | 1 + proto | 2 +- src/mesh/MeshRadio.h | 93 ++++--------------------------------- src/mesh/NodeDB.cpp | 45 ++++++++++++++---- src/mesh/RadioInterface.cpp | 41 +++++++++++++--- src/mesh/mesh.pb.c | 3 +- src/mesh/mesh.pb.h | 30 +++++++++--- 7 files changed, 107 insertions(+), 108 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9b72a2a2f..8ea4339da 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -56,6 +56,7 @@ "HFSR", "Meshtastic", "NEMAGPS", + "RDEF", "Ublox", "bkpt", "cfsr", diff --git a/proto b/proto index 4e431c841..5cdd7bff5 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 4e431c841015edfdde925acf5ee4ac0a2272edff +Subproject commit 5cdd7bff56b0ea54351e5ea0e358e864b061078f diff --git a/src/mesh/MeshRadio.h b/src/mesh/MeshRadio.h index 070c7c9a7..2cee8f89a 100644 --- a/src/mesh/MeshRadio.h +++ b/src/mesh/MeshRadio.h @@ -6,87 +6,14 @@ #include "configuration.h" #include "mesh.pb.h" -// US channel settings -#define CH0_US 903.08f // MHz -#define CH_SPACING_US 2.16f // MHz -#define NUM_CHANNELS_US 13 +// Map from old region names to new region enums +struct RegionInfo { + RegionCode code; + uint8_t numChannels; + uint8_t powerLimit; // Or zero for not set + float freq; + float spacing; + const char *name; // EU433 etc +}; -// EU433 channel settings -#define CH0_EU433 433.175f // MHz -#define CH_SPACING_EU433 0.2f // MHz -#define NUM_CHANNELS_EU433 8 - -// EU865 channel settings -#define CH0_EU865 865.2f // MHz -#define CH_SPACING_EU865 0.3f // MHz -#define NUM_CHANNELS_EU865 10 - -// CN channel settings -#define CH0_CN 470.0f // MHz -#define CH_SPACING_CN 2.0f // MHz FIXME, this is just a guess for 470-510 -#define NUM_CHANNELS_CN 20 - -// JP channel settings (AS1 bandplan) -#define CH0_JP 920.0f // MHz -#define CH_SPACING_JP 0.5f -#define NUM_CHANNELS_JP 10 - -// TW channel settings (AS2 bandplan 923-925MHz) -#define CH0_TW 923.0f // MHz -#define CH_SPACING_TW 0.2 -#define NUM_CHANNELS_TW 10 - -// AU/NZ channel settings 915-928MHz -#define CH0_ANZ 916.0f // MHz - avoid overcrowding on 915.0 -#define CH_SPACING_ANZ 0.5f -#define NUM_CHANNELS_ANZ 20 - -// KR channel settings (KR920-923) -// Start from TTN download channel freq. (921.9f is for download, others are for uplink) -#define CH0_KR 921.9f // MHz -#define CH_SPACING_KR 0.2f -#define NUM_CHANNELS_KR 8 - -// FIXME add defs for other regions and use them here -#ifdef HW_VERSION_US -#define CH0 CH0_US -#define CH_SPACING CH_SPACING_US -#define NUM_CHANNELS NUM_CHANNELS_US -#elif defined(HW_VERSION_EU433) -#define CH0 CH0_EU433 -#define CH_SPACING CH_SPACING_EU433 -#define NUM_CHANNELS NUM_CHANNELS_EU433 -#elif defined(HW_VERSION_EU865) -#define CH0 CH0_EU865 -#define CH_SPACING CH_SPACING_EU865 -#define NUM_CHANNELS NUM_CHANNELS_EU865 -#elif defined(HW_VERSION_CN) -#define CH0 CH0_CN -#define CH_SPACING CH_SPACING_CN -#define NUM_CHANNELS NUM_CHANNELS_CN -#elif defined(HW_VERSION_JP) -// Also called AS1 bandplan -#define CH0 CH0_JP -#define CH_SPACING CH_SPACING_JP -#define NUM_CHANNELS NUM_CHANNELS_JP -#elif defined(HW_VERSION_TW) -// Also called AS2 bandplan -#define CH0 CH0_TW -#define CH_SPACING CH_SPACING_TW -#define NUM_CHANNELS NUM_CHANNELS_TW -#elif defined(HW_VERSION_ANZ) -// Australia and NZ -#define CH0 CH0_ANZ -#define CH_SPACING CH_SPACING_ANZ -#define NUM_CHANNELS NUM_CHANNELS_ANZ -#elif defined(HW_VERSION_KR) -// Republic of Korea -#define CH0 CH0_KR -#define CH_SPACING CH_SPACING_KR -#define NUM_CHANNELS NUM_CHANNELS_KR -#else -// HW version not set - assume US -#define CH0 CH0_US -#define CH_SPACING CH_SPACING_US -#define NUM_CHANNELS NUM_CHANNELS_US -#endif \ No newline at end of file +extern const RegionInfo regions[]; \ No newline at end of file diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 9f545a3fa..1f34eb5df 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -6,6 +6,7 @@ #include "CryptoEngine.h" #include "GPS.h" +#include "MeshRadio.h" #include "NodeDB.h" #include "PacketHistory.h" #include "PowerFSM.h" @@ -13,9 +14,9 @@ #include "configuration.h" #include "error.h" #include "mesh-pb-constants.h" +#include "meshwifi/meshwifi.h" #include #include -#include "meshwifi/meshwifi.h" NodeDB nodeDB; @@ -118,8 +119,6 @@ bool NodeDB::resetRadioConfig() } else if (radioConfig.preferences.sds_secs == 0) { DEBUG_MSG("Fixing bogus RadioConfig!\n"); - radioConfig.preferences.factory_reset = false; // never save this to disk - radioConfig.preferences.send_owner_interval = 4; // per sw-design.md radioConfig.preferences.position_broadcast_secs = 15 * 60; radioConfig.preferences.wait_bluetooth_secs = 120; @@ -163,6 +162,10 @@ bool NodeDB::resetRadioConfig() void NodeDB::installDefaultDeviceState() { + // We try to preserve the region setting because it will really bum users out if we discard it + String oldRegion = myNodeInfo.region; + RegionCode oldRegionCode = radioConfig.preferences.region; + memset(&devicestate, 0, sizeof(devicestate)); *numNodes = 0; // Forget node DB @@ -195,6 +198,12 @@ void NodeDB::installDefaultDeviceState() // owner.short_name now sprintf(owner.long_name, "Unknown %02x%02x", ourMacAddr[4], ourMacAddr[5]); sprintf(owner.short_name, "?%02X", (unsigned)(myNodeInfo.my_node_num & 0xff)); + + // Restore region if possible + if (oldRegionCode != RegionCode_Unset) + radioConfig.preferences.region = oldRegionCode; + if (oldRegion.length()) + strcpy(myNodeInfo.region, oldRegion.c_str()); } void NodeDB::init() @@ -227,13 +236,29 @@ void NodeDB::init() // We set these _after_ loading from disk - because they come from the build and are more trusted than // what is stored in flash - strncpy(myNodeInfo.region, optstr(HW_VERSION), sizeof(myNodeInfo.region)); + if (xstr(HW_VERSION)[0]) + strncpy(myNodeInfo.region, optstr(HW_VERSION), sizeof(myNodeInfo.region)); + else + DEBUG_MSG("This build does not specify a HW_VERSION\n"); // Eventually new builds will no longer include this build flag + + // Check for the old style of region code strings, if found, convert to the new enum. + // Those strings will look like "1.0-EU433" + if (radioConfig.preferences.region == RegionCode_Unset && strncmp(myNodeInfo.region, "1.0-", 4) == 0) { + const char *regionStr = myNodeInfo.region + 4; // EU433 or whatever + for (const RegionInfo *r = regions; r->code != RegionCode_Unset; r++) + if (strcmp(r->name, regionStr) == 0) { + radioConfig.preferences.region = r->code; + break; + } + } + strncpy(myNodeInfo.firmware_version, optstr(APP_VERSION), sizeof(myNodeInfo.firmware_version)); strncpy(myNodeInfo.hw_model, HW_VENDOR, sizeof(myNodeInfo.hw_model)); resetRadioConfig(); // If bogus settings got saved, then fix them - DEBUG_MSG("NODENUM=0x%x, dbsize=%d\n", myNodeInfo.my_node_num, *numNodes); + DEBUG_MSG("legacy_region=%s, region=%d, NODENUM=0x%x, dbsize=%d\n", myNodeInfo.region, radioConfig.preferences.region, + myNodeInfo.my_node_num, *numNodes); } // We reserve a few nodenums for future use @@ -421,11 +446,11 @@ void NodeDB::updateFrom(const MeshPacket &mp) powerFSM.trigger(EVENT_RECEIVED_TEXT_MSG); notifyObservers(true); // Force an update whether or not our node counts have changed -// This is going into the wifidev feature branch -// Only update the WebUI if WiFi is enabled -//#if WiFi_MODE != 0 -// notifyWebUI(); -//#endif + // This is going into the wifidev feature branch + // Only update the WebUI if WiFi is enabled + //#if WiFi_MODE != 0 + // notifyWebUI(); + //#endif } } break; diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 1a08f282e..1fcee0dc3 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -10,6 +10,24 @@ #include #include +#define RDEF(name, freq, spacing, num_ch, power_limit) \ + { \ + RegionCode_##name, num_ch, power_limit, freq, spacing, #name \ + } + +const RegionInfo regions[] = { + RDEF(US, 903.08f, 2.16f, 13, 0), RDEF(EU433, 433.175f, 0.2f, 8, 0), RDEF(EU865, 865.2f, 0.3f, 10, 0), + RDEF(CN, 470.0f, 2.0f, 20, 0), + RDEF(JP, 920.0f, 0.5f, 10, 13), // See https://github.com/meshtastic/Meshtastic-device/issues/346 power level 13 + RDEF(ANZ, 916.0f, 0.5f, 20, 0), // AU/NZ channel settings 915-928MHz + RDEF(KR, 921.9f, 0.2f, 8, 0), // KR channel settings (KR920-923) Start from TTN download channel + // freq. (921.9f is for download, others are for uplink) + RDEF(TW, 923.0f, 0.2f, 10, 0), // TW channel settings (AS2 bandplan 923-925MHz) + RDEF(Unset, 903.08f, 2.16f, 13, 0) // Assume US freqs if unset, Must be last +}; + +static const RegionInfo *myRegion; + /** * ## LoRaWAN for North America @@ -77,7 +95,15 @@ RadioInterface::RadioInterface() { assert(sizeof(PacketHeader) == 4 || sizeof(PacketHeader) == 16); // make sure the compiler did what we expected - myNodeInfo.num_channels = NUM_CHANNELS; + if (!myRegion) { + const RegionInfo *r = regions; + for (; r->code != RegionCode_Unset && r->code != radioConfig.preferences.region; r++) + ; + myRegion = r; + DEBUG_MSG("Wanted region %d, using %s\n", radioConfig.preferences.region, r->name); + + myNodeInfo.num_channels = myRegion->numChannels; // Tell our android app how many channels we have + } // Can't print strings this early - serial not setup yet // DEBUG_MSG("Set meshradio defaults name=%s\n", channelSettings.name); @@ -127,9 +153,12 @@ void RadioInterface::applyModemConfig() power = channelSettings.tx_power; + assert(myRegion); // Should have been found in init + // If user has manually specified a channel num, then use that, otherwise generate one by hashing the name - int channel_num = (channelSettings.channel_num ? channelSettings.channel_num - 1 : hash(channelSettings.name)) % NUM_CHANNELS; - freq = CH0 + CH_SPACING * channel_num; + int channel_num = + (channelSettings.channel_num ? channelSettings.channel_num - 1 : hash(channelSettings.name)) % myRegion->numChannels; + freq = myRegion->freq + myRegion->spacing * channel_num; DEBUG_MSG("Set radio: name=%s, config=%u, ch=%d, power=%d\n", channelSettings.name, channelSettings.modem_config, channel_num, power); @@ -143,9 +172,9 @@ void RadioInterface::limitPower() { uint8_t maxPower = 255; // No limit -#ifdef HW_VERSION_JP - maxPower = 13; // See https://github.com/meshtastic/Meshtastic-device/issues/346 -#endif + if (myRegion->powerLimit) + maxPower = myRegion->powerLimit; + if (power > maxPower) { DEBUG_MSG("Lowering transmit power because of regulatory limits\n"); power = maxPower; diff --git a/src/mesh/mesh.pb.c b/src/mesh/mesh.pb.c index b2d1ceb23..11ec3f49f 100644 --- a/src/mesh/mesh.pb.c +++ b/src/mesh/mesh.pb.c @@ -27,7 +27,7 @@ PB_BIND(MeshPacket, MeshPacket, 2) PB_BIND(ChannelSettings, ChannelSettings, AUTO) -PB_BIND(RadioConfig, RadioConfig, 2) +PB_BIND(RadioConfig, RadioConfig, AUTO) PB_BIND(RadioConfig_UserPreferences, RadioConfig_UserPreferences, 2) @@ -59,3 +59,4 @@ PB_BIND(ManufacturingData, ManufacturingData, AUTO) + diff --git a/src/mesh/mesh.pb.h b/src/mesh/mesh.pb.h index 6fbc79f7c..b726ab6e1 100644 --- a/src/mesh/mesh.pb.h +++ b/src/mesh/mesh.pb.h @@ -25,6 +25,18 @@ typedef enum _Constants { Constants_Unused = 0 } Constants; +typedef enum _RegionCode { + RegionCode_Unset = 0, + RegionCode_US = 1, + RegionCode_EU433 = 2, + RegionCode_EU865 = 3, + RegionCode_CN = 4, + RegionCode_JP = 5, + RegionCode_ANZ = 6, + RegionCode_KR = 7, + RegionCode_TW = 8 +} RegionCode; + typedef enum _Data_Type { Data_Type_OPAQUE = 0, Data_Type_CLEAR_TEXT = 1, @@ -108,7 +120,7 @@ typedef struct _RadioConfig_UserPreferences { char wifi_ssid[33]; char wifi_password[64]; bool wifi_ap_mode; - char region[6]; + RegionCode region; bool factory_reset; pb_size_t ignore_incoming_count; uint32_t ignore_incoming[3]; @@ -232,6 +244,10 @@ typedef struct _ToRadio { #define _Constants_MAX Constants_Unused #define _Constants_ARRAYSIZE ((Constants)(Constants_Unused+1)) +#define _RegionCode_MIN RegionCode_Unset +#define _RegionCode_MAX RegionCode_TW +#define _RegionCode_ARRAYSIZE ((RegionCode)(RegionCode_TW+1)) + #define _Data_Type_MIN Data_Type_OPAQUE #define _Data_Type_MAX Data_Type_CLEAR_READACK #define _Data_Type_ARRAYSIZE ((Data_Type)(Data_Type_CLEAR_READACK+1)) @@ -250,7 +266,7 @@ typedef struct _ToRadio { #define MeshPacket_init_default {0, 0, 0, {SubPacket_init_default}, 0, 0, 0, 0, 0} #define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0} #define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default, false, ChannelSettings_init_default} -#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, "", 0, 0, {0, 0, 0}} +#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, 0, 0, {0, 0, 0}} #define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0} #define MyNodeInfo_init_default {0, 0, 0, "", "", "", 0, 0, 0, 0, 0, 0, 0, 0} #define DeviceState_init_default {false, RadioConfig_init_default, false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0} @@ -266,7 +282,7 @@ typedef struct _ToRadio { #define MeshPacket_init_zero {0, 0, 0, {SubPacket_init_zero}, 0, 0, 0, 0, 0} #define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0} #define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero, false, ChannelSettings_init_zero} -#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, "", 0, 0, {0, 0, 0}} +#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, 0, 0, {0, 0, 0}} #define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0} #define MyNodeInfo_init_zero {0, 0, 0, "", "", "", 0, 0, 0, 0, 0, 0, 0, 0} #define DeviceState_init_zero {false, RadioConfig_init_zero, false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0} @@ -481,7 +497,7 @@ X(a, STATIC, SINGULAR, UINT32, min_wake_secs, 11) \ X(a, STATIC, SINGULAR, STRING, wifi_ssid, 12) \ X(a, STATIC, SINGULAR, STRING, wifi_password, 13) \ X(a, STATIC, SINGULAR, BOOL, wifi_ap_mode, 14) \ -X(a, STATIC, SINGULAR, STRING, region, 15) \ +X(a, STATIC, SINGULAR, UENUM, region, 15) \ X(a, STATIC, SINGULAR, BOOL, factory_reset, 100) \ X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103) #define RadioConfig_UserPreferences_CALLBACK NULL @@ -619,11 +635,11 @@ extern const pb_msgdesc_t ManufacturingData_msg; #define SubPacket_size 274 #define MeshPacket_size 313 #define ChannelSettings_size 84 -#define RadioConfig_size 287 -#define RadioConfig_UserPreferences_size 198 +#define RadioConfig_size 282 +#define RadioConfig_UserPreferences_size 193 #define NodeInfo_size 132 #define MyNodeInfo_size 110 -#define DeviceState_size 5439 +#define DeviceState_size 5434 #define DebugString_size 258 #define FromRadio_size 322 #define ToRadio_size 316 From d1c30786983ae2803e41a079747748a2d127cf17 Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 25 Sep 2020 12:52:26 -0700 Subject: [PATCH 31/34] shrink guard for channel settings lock --- src/graphics/Screen.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 0b57bfb3e..14a202458 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -31,8 +31,8 @@ along with this program. If not, see . #include "graphics/images.h" #include "main.h" #include "mesh-pb-constants.h" -#include "target_specific.h" #include "meshwifi/meshwifi.h" +#include "target_specific.h" #include "utils.h" using namespace meshtastic; /** @todo remove */ @@ -809,18 +809,18 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 { concurrency::LockGuard guard(&lock); snprintf(channelStr, sizeof(channelStr), "%s", channelName.c_str()); - - // Display power status - if (powerStatus->getHasBattery()) - drawBattery(display, x, y + 2, imgBattery, powerStatus); - else if (powerStatus->knowsUSB()) - display->drawFastImage(x, y + 2, 16, 8, powerStatus->getHasUSB() ? imgUSB : imgPower); - // Display nodes status - drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 2, nodeStatus); - // Display GPS status - drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 2, gpsStatus); } + // Display power status + if (powerStatus->getHasBattery()) + drawBattery(display, x, y + 2, imgBattery, powerStatus); + else if (powerStatus->knowsUSB()) + display->drawFastImage(x, y + 2, 16, 8, powerStatus->getHasUSB() ? imgUSB : imgPower); + // Display nodes status + drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 2, nodeStatus); + // Display GPS status + drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 2, gpsStatus); + // Draw the channel name display->drawString(x, y + FONT_HEIGHT, channelStr); // Draw our hardware ID to assist with bluetooth pairing From 2996c7c8e26472e69686a4221ca446f7ad9b7370 Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 25 Sep 2020 16:18:30 -0700 Subject: [PATCH 32/34] Make tcp API now work. Sample usage and caveats below: Sample usage: First configure device to use @mc-hamster's new wifi stuff: meshtastic --set wifi_ssid mylanname --set wifi_password mylanpassword Then reboot the device (so wifi starts up). (assuming device was assigned addr 192.168.81.45) meshtastic --info --host 192.168.81.45 (See the usual device info you previously had to get over USB) Caveats: * Currently we are limiting to one active TCP connection open at once, if you open a new session the old one is closed automatically * There are no access controls/authentication needed to open a TCP connection to the device * Currently main.cpp is kinda dumb about how we should schedule work and we rely on too many helper loop() functions. Very soon in my queue (related to all the other cleanup) is to add a basic notion of coroutines, so that we can get away from freertos threads and this old school arduino loop function. Once that cleanup happens we can the a) have much lower battery consumption (always) and b) super fast response for all operations. --- src/esp32/WiFiServerAPI.cpp | 10 +++++++++- src/esp32/WiFiServerAPI.h | 7 +++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/esp32/WiFiServerAPI.cpp b/src/esp32/WiFiServerAPI.cpp index 974b0f3c1..109340bff 100644 --- a/src/esp32/WiFiServerAPI.cpp +++ b/src/esp32/WiFiServerAPI.cpp @@ -52,6 +52,14 @@ void WiFiServerPort::loop() { auto client = available(); if (client) { - new WiFiServerAPI(client); + // Close any previous connection (see FIXME in header file) + if (openAPI) + delete openAPI; + + openAPI = new WiFiServerAPI(client); } + + if (openAPI) + // Allow idle processing so the API can read from its incoming stream + openAPI->loop(); } \ No newline at end of file diff --git a/src/esp32/WiFiServerAPI.h b/src/esp32/WiFiServerAPI.h index dcafa419d..a9b1e39b4 100644 --- a/src/esp32/WiFiServerAPI.h +++ b/src/esp32/WiFiServerAPI.h @@ -29,6 +29,13 @@ class WiFiServerAPI : public StreamAPI */ class WiFiServerPort : public WiFiServer { + /** The currently open port + * + * FIXME: We currently only allow one open TCP connection at a time, because we depend on the loop() call in this class to + * delegate to the worker. Once coroutines are implemented we can relax this restriction. + */ + WiFiServerAPI *openAPI = NULL; + public: WiFiServerPort(); From 28119bf1bfaccb82b604431cc7bb7b452a203bee Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sat, 26 Sep 2020 00:01:02 -0700 Subject: [PATCH 33/34] Fix for #439 and some cleanup --- src/esp32/WiFiServerAPI.cpp | 2 +- src/graphics/Screen.cpp | 13 +++++++------ src/meshwifi/meshwifi.cpp | 32 ++++++++++++++++---------------- src/meshwifi/meshwifi.h | 3 ++- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/esp32/WiFiServerAPI.cpp b/src/esp32/WiFiServerAPI.cpp index 109340bff..aa5963882 100644 --- a/src/esp32/WiFiServerAPI.cpp +++ b/src/esp32/WiFiServerAPI.cpp @@ -33,7 +33,7 @@ void WiFiServerAPI::loop() if (client.connected()) { StreamAPI::loop(); } else { - DEBUG_MSG("Client dropped connection, closing UDP server\n"); + DEBUG_MSG("Client dropped connection, closing TCP server\n"); delete this; } } diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 14a202458..3b171f397 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -32,6 +32,7 @@ along with this program. If not, see . #include "main.h" #include "mesh-pb-constants.h" #include "meshwifi/meshwifi.h" +#include "nimble/BluetoothUtil.h" #include "target_specific.h" #include "utils.h" @@ -942,7 +943,7 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i } else if (getWifiDisconnectReason() == 200) { display->drawString(x, y + FONT_HEIGHT * 1, "BEACON_TIMEOUT"); } else if (getWifiDisconnectReason() == 201) { - display->drawString(x, y + FONT_HEIGHT * 1, "NO_AP_FOUND"); + display->drawString(x, y + FONT_HEIGHT * 1, "AP Not Found"); } else if (getWifiDisconnectReason() == 202) { display->drawString(x, y + FONT_HEIGHT * 1, "AUTH_FAIL"); } else if (getWifiDisconnectReason() == 203) { @@ -950,7 +951,7 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i } else if (getWifiDisconnectReason() == 204) { display->drawString(x, y + FONT_HEIGHT * 1, "HANDSHAKE_TIMEOUT"); } else if (getWifiDisconnectReason() == 205) { - display->drawString(x, y + FONT_HEIGHT * 1, "CONNECTION_FAIL"); + display->drawString(x, y + FONT_HEIGHT * 1, "Connection Failed"); } else { display->drawString(x, y + FONT_HEIGHT * 1, "Unknown Status"); } @@ -992,8 +993,10 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat display->drawString(x, y, String("USB")); } - // TODO: Display status of the BT radio - // display->drawString(x + SCREEN_WIDTH - display->getStringWidth("BT On"), y, "BT On"); + display->drawString(x + SCREEN_WIDTH - display->getStringWidth("Mode " + String(channelSettings.modem_config)), + y, "Mode " + String(channelSettings.modem_config)); + + // Line 2 uint32_t currentMillis = millis(); @@ -1009,8 +1012,6 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat display->drawString(x, y + FONT_HEIGHT * 1, String(days) + "d " + (hours < 10 ? "0" : "") + String(hours) + ":" + (minutes < 10 ? "0" : "") + String(minutes) + ":" + (seconds < 10 ? "0" : "") + String(seconds)); - display->drawString(x + SCREEN_WIDTH - display->getStringWidth("Mode " + String(channelSettings.modem_config)), - y + FONT_HEIGHT * 1, "Mode " + String(channelSettings.modem_config)); // Line 4 drawGPScoordinates(display, x, y + FONT_HEIGHT * 3, gpsStatus); diff --git a/src/meshwifi/meshwifi.cpp b/src/meshwifi/meshwifi.cpp index 84a9a5a57..0c775b5c8 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -8,9 +8,10 @@ #include static void WiFiEvent(WiFiEvent_t event); -// static void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info); +// DNS Server for the Captive Portal DNSServer dnsServer; + static WiFiServerPort *apiPort; uint8_t wifiDisconnectReason = 0; @@ -60,18 +61,6 @@ void initWifi() const char *wifiName = radioConfig.preferences.wifi_ssid; const char *wifiPsw = radioConfig.preferences.wifi_password; - /* - if (0) { - radioConfig.preferences.wifi_ap_mode = 1; - strcpy(radioConfig.preferences.wifi_ssid, "MeshTest2"); - strcpy(radioConfig.preferences.wifi_password, "12345678"); - } else { - radioConfig.preferences.wifi_ap_mode = 0; - strcpy(radioConfig.preferences.wifi_ssid, "meshtastic"); - strcpy(radioConfig.preferences.wifi_password, "meshtastic!"); - } - */ - if (*wifiName && *wifiPsw) { if (radioConfig.preferences.wifi_ap_mode) { @@ -89,11 +78,20 @@ void initWifi() WiFi.onEvent(WiFiEvent); // esp_wifi_set_ps(WIFI_PS_NONE); // Disable power saving - WiFiEventId_t eventID = WiFi.onEvent( + //WiFiEventId_t eventID = WiFi.onEvent( + WiFi.onEvent( [](WiFiEvent_t event, WiFiEventInfo_t info) { Serial.print("\nWiFi lost connection. Reason: "); Serial.println(info.disconnected.reason); - // wifiDisconnectReason = info.disconnected.reason; + + /* + If we are disconnected from the AP for some reason, + save the error code. + + For a reference to the codes: + https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html#wi-fi-reason-code + */ + wifiDisconnectReason = info.disconnected.reason; }, WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED); @@ -125,6 +123,8 @@ static void initApiServer() apiPort->init(); } } + +// Called by the Espressif SDK to static void WiFiEvent(WiFiEvent_t event) { DEBUG_MSG("************ [WiFi-event] event: %d ************\n", event); @@ -249,7 +249,7 @@ void reconnectWiFi() } } -uint8_t getWifiDisconnectReason() +uint8_t getWifiDisconnectReason() { return wifiDisconnectReason; } \ No newline at end of file diff --git a/src/meshwifi/meshwifi.h b/src/meshwifi/meshwifi.h index d38b2a41e..f22d69a63 100644 --- a/src/meshwifi/meshwifi.h +++ b/src/meshwifi/meshwifi.h @@ -21,4 +21,5 @@ void handleDNSResponse(); void reconnectWiFi(); -uint8_t getWifiDisconnectReason(); \ No newline at end of file +uint8_t getWifiDisconnectReason(); + From 6f444ed4b5eeea149607dc7d488bb6354aa457b7 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sat, 26 Sep 2020 00:03:23 -0700 Subject: [PATCH 34/34] Accidently left #include "nimble/BluetoothUtil.h" in screen --- src/graphics/Screen.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 3b171f397..0706ddb44 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -32,7 +32,6 @@ along with this program. If not, see . #include "main.h" #include "mesh-pb-constants.h" #include "meshwifi/meshwifi.h" -#include "nimble/BluetoothUtil.h" #include "target_specific.h" #include "utils.h"