diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 5229f566..29637934 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -32,6 +32,8 @@ 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 */ @@ -708,6 +710,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 +747,11 @@ void Screen::setFrames() // call a method on debugInfoScreen object (for more details) normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline; + if (isWifiAvailable()) { + // call a method on debugInfoScreen object (for more details) + normalFrames[numframes++] = &Screen::drawDebugInfoWiFiTrampoline; + } + ui.setFrames(normalFrames, numframes); ui.enableAllIndicators(); @@ -827,6 +840,38 @@ 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); + + // 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->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) + 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 c9ab8544..8f5a6de2 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 0a474e08..b0d133f2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,6 +41,8 @@ #include "timing.h" #include #include +#include "meshwifi/meshwifi.h" +#include "meshwifi/meshhttp.h" // #include #ifndef NO_ESP32 @@ -325,6 +327,9 @@ void setup() } #endif + // Initialize Wifi + initWifi(); + if (!rIf) recordCriticalError(ErrNoRadio); else @@ -416,5 +421,8 @@ void loop() // feel slow msecstosleep = 10; + // TODO: This should go into a thread handled by FreeRTOS. + handleWebResponse(); + delay(msecstosleep); } diff --git a/src/main.h b/src/main.h index fb64d9ff..39b1364f 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 93d0787d..07a97acf 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,12 @@ 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 + +// 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/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp new file mode 100644 index 00000000..f52cade5 --- /dev/null +++ b/src/meshwifi/meshhttp.cpp @@ -0,0 +1,93 @@ +#include +#include +#include "configuration.h" +#include "main.h" +#include "NodeDB.h" +#include "meshwifi/meshwifi.h" +#include "meshwifi/meshhttp.h" + + +WebServer webserver(80); + +String something = ""; +String sender = ""; + + +void handleWebResponse() { + if (isWifiAvailable() == 0) { + return; + } + + 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 00000000..cbff51db --- /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 new file mode 100644 index 00000000..14ac8a2a --- /dev/null +++ b/src/meshwifi/meshwifi.cpp @@ -0,0 +1,166 @@ +#include "meshwifi.h" +#include +#include "configuration.h" +#include "main.h" +#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() +{ + /* + 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); + 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); + //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()); + } 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\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()); + + // 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 new file mode 100644 index 00000000..044839ab --- /dev/null +++ b/src/meshwifi/meshwifi.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include +#include + +void initWifi(); + +void deinitWifi(); + +void WiFiEvent(WiFiEvent_t event); + +bool isWifiAvailable(); \ No newline at end of file diff --git a/src/nimble/BluetoothUtil.cpp b/src/nimble/BluetoothUtil.cpp index 490bc13d..a78b0098 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" @@ -13,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,33 +503,8 @@ 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; +bool firstTime = 1; // Enable/disable bluetooth. void setBluetoothEnable(bool on) @@ -542,11 +517,19 @@ 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(); + + // Don't try to reconnect wifi before bluetooth is configured. + // WiFi is initialized from main.cpp in setup() . + if (firstTime) { + firstTime = 0; + } else { + initWifi(); + } } else { // We have to totally teardown our bluetooth objects to prevent leaks + deinitWifi(); // shutdown wifi deinitBLE(); - 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();