From cdf416cb730ad4e51d02bdb289691fa5adb2fb2f Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Thu, 31 Dec 2020 09:52:08 +0800 Subject: [PATCH 01/18] partial fix for #608 - when a new TCP API connection arrives, close old one completely --- src/esp32/WiFiServerAPI.cpp | 33 ++++++++++++++++++++++----------- src/esp32/WiFiServerAPI.h | 6 +++++- src/mesh/PhoneAPI.cpp | 8 +++++++- src/mesh/PhoneAPI.h | 7 +++++-- 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/esp32/WiFiServerAPI.cpp b/src/esp32/WiFiServerAPI.cpp index 3b11c2ae4..fac955ccc 100644 --- a/src/esp32/WiFiServerAPI.cpp +++ b/src/esp32/WiFiServerAPI.cpp @@ -28,18 +28,19 @@ void WiFiServerAPI::onConnectionChanged(bool connected) } } -void WiFiServerAPI::loop() +/// override close to also shutdown the TCP link +void WiFiServerAPI::close() { + client.stop(); // drop tcp connection + StreamAPI::close(); +} + +bool WiFiServerAPI::loop() { if (client.connected()) { StreamAPI::loop(); - } else if(isConnected) { - // If our API link was up, shut it down - - DEBUG_MSG("Client dropped connection, closing API client\n"); - // Note: we can't call delete here because this object includes other state - // besides the stream API. Instead kill it later when we start a new instance - // delete this; - close(); + return true; + } else { + return false; } } @@ -58,15 +59,25 @@ int32_t WiFiServerPort::runOnce() auto client = available(); if (client) { // Close any previous connection (see FIXME in header file) - if (openAPI) + if (openAPI) { + DEBUG_MSG("Force closing previous TCP connection\n"); delete openAPI; + } openAPI = new WiFiServerAPI(client); } if (openAPI) { // Allow idle processing so the API can read from its incoming stream - openAPI->loop(); + if(!openAPI->loop()) { + // If our API link was up, shut it down + + DEBUG_MSG("Client dropped connection, closing API client\n"); + // Note: we can't call delete here because this object includes other state + // besides the stream API. Instead kill it later when we start a new instance + delete openAPI; + openAPI = NULL; + } return 0; // run fast while our API server is running } else return 100; // only check occasionally for incoming connections diff --git a/src/esp32/WiFiServerAPI.h b/src/esp32/WiFiServerAPI.h index 19f99cbc5..963800203 100644 --- a/src/esp32/WiFiServerAPI.h +++ b/src/esp32/WiFiServerAPI.h @@ -18,7 +18,11 @@ class WiFiServerAPI : public StreamAPI virtual ~WiFiServerAPI(); - virtual void loop(); // Check for dropped client connections + /// @return true if we want to keep running, or false if we are ready to be destroyed + virtual bool loop(); // Check for dropped client connections + + /// override close to also shutdown the TCP link + virtual void close(); protected: /// Hookable to find out when connection changes diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index a0cad4273..545ef2b90 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -21,11 +21,17 @@ void PhoneAPI::init() observe(&service.fromNumChanged); } +PhoneAPI::~PhoneAPI() { + close(); +} + void PhoneAPI::close() { unobserve(); state = STATE_SEND_NOTHING; + bool oldConnected = isConnected; isConnected = false; - onConnectionChanged(isConnected); + if(oldConnected != isConnected) + onConnectionChanged(isConnected); } void PhoneAPI::checkConnectionTimeout() diff --git a/src/mesh/PhoneAPI.h b/src/mesh/PhoneAPI.h index 202f7fa2d..3cfd97441 100644 --- a/src/mesh/PhoneAPI.h +++ b/src/mesh/PhoneAPI.h @@ -55,12 +55,15 @@ class PhoneAPI public: PhoneAPI(); + /// Destructor - calls close() + virtual ~PhoneAPI(); + /// Do late init that can't happen at constructor time virtual void init(); // Call this when the client drops the connection, resets the state to STATE_SEND_NOTHING - // Unregisters our observer - void close(); + // Unregisters our observer. A closed connection **can** be reopened by calling init again. + virtual void close(); /** * Handle a ToRadio protobuf From f6336855d037cf64a74f5b755a62b8188605278e Mon Sep 17 00:00:00 2001 From: Wei Fang Date: Wed, 30 Dec 2020 21:11:03 -0800 Subject: [PATCH 02/18] Fix GPS turned on then off immediately every 2 minutes --- src/gps/GPS.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index c0e336f0c..04aa2c7af 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -239,6 +239,7 @@ int32_t GPS::runOnce() } // We've been awake too long - force sleep + now = millis(); auto wakeTime = getWakeTime(); bool tooLong = wakeTime != UINT32_MAX && (now - lastWakeStartMsec) > wakeTime; From ebdad76fb2a35dc61559174e58e57ed7b731d5c4 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 2 Jan 2021 11:06:38 +0800 Subject: [PATCH 03/18] portduino: gpios now kinda work on linux --- platformio.ini | 2 +- src/portduino/PortduinoGlue.cpp | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 50d381c8b..78da2c6e1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [platformio] -default_envs = tbeam # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here +default_envs = linux # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here ;default_envs = heltec # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here [common] diff --git a/src/portduino/PortduinoGlue.cpp b/src/portduino/PortduinoGlue.cpp index 0862e33f9..c8a7e84c4 100644 --- a/src/portduino/PortduinoGlue.cpp +++ b/src/portduino/PortduinoGlue.cpp @@ -1,5 +1,6 @@ #include "CryptoEngine.h" #include "target_specific.h" +#include "PortduinoGPIO.h" #include #include "sleep.h" @@ -34,4 +35,15 @@ void cpuDeepSleep(uint64_t msecs) { // FIXME - implement real crypto for linux CryptoEngine *crypto = new CryptoEngine(); -void updateBatteryLevel(uint8_t level) NOT_IMPLEMENTED("updateBatteryLevel"); \ No newline at end of file +void updateBatteryLevel(uint8_t level) NOT_IMPLEMENTED("updateBatteryLevel"); + + + +/** apps run under portduino can optionally define a portduinoSetup() to + * use portduino specific init code (such as gpioBind) to setup portduino on their host machine, + * before running 'arduino' code. + */ +void portduinoSetup() { + printf("Setting up Meshtastic on Porduino...\n"); + gpioBind((new SimGPIOPin(RF95_NSS, "RF95_NSS"))->setSilent()); +} From 5ceee50bb5dd81a878910ca8adb085a1395056a1 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 2 Jan 2021 11:23:18 +0800 Subject: [PATCH 04/18] bug: we've always been setting gpio 0 as an input on rf95 based devices found because portduino provides full visibility to all IO operations to the hw simulator. --- src/mesh/RF95Interface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/RF95Interface.cpp b/src/mesh/RF95Interface.cpp index 60596468b..a94a8d129 100644 --- a/src/mesh/RF95Interface.cpp +++ b/src/mesh/RF95Interface.cpp @@ -12,7 +12,7 @@ #define POWER_DEFAULT 17 // How much power to use if the user hasn't set a power level RF95Interface::RF95Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, SPIClass &spi) - : RadioLibInterface(cs, irq, rst, 0, spi) + : RadioLibInterface(cs, irq, rst, RADIOLIB_NC, spi) { // FIXME - we assume devices never get destroyed } From b0e3a7524f28346f04f39349496aca4d3de4b397 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 2 Jan 2021 11:23:30 +0800 Subject: [PATCH 05/18] assign more portduino pins --- src/portduino/PortduinoGlue.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/portduino/PortduinoGlue.cpp b/src/portduino/PortduinoGlue.cpp index c8a7e84c4..ce63f8dc4 100644 --- a/src/portduino/PortduinoGlue.cpp +++ b/src/portduino/PortduinoGlue.cpp @@ -45,5 +45,7 @@ void updateBatteryLevel(uint8_t level) NOT_IMPLEMENTED("updateBatteryLevel"); */ void portduinoSetup() { printf("Setting up Meshtastic on Porduino...\n"); + gpioBind((new SimGPIOPin(LORA_DIO0, "LORA_DIO0"))); + gpioBind((new SimGPIOPin(LORA_RESET, "LORA_RESET"))); gpioBind((new SimGPIOPin(RF95_NSS, "RF95_NSS"))->setSilent()); } From aa176b6593c8be4ba462155f1bc4b2170b1042cf Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 2 Jan 2021 12:38:18 +0800 Subject: [PATCH 06/18] portuino now kinda works with the pinetab lora USB module. still need to add an AEX256 impl for the linux port and optimize a bit --- platformio.ini | 2 +- src/configuration.h | 2 +- src/mesh/RF95Interface.h | 3 ++ src/portduino/PortduinoGlue.cpp | 50 +++++++++++++++++++++++++++++++-- 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/platformio.ini b/platformio.ini index 78da2c6e1..5be5ac571 100644 --- a/platformio.ini +++ b/platformio.ini @@ -65,7 +65,7 @@ lib_deps = 1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib https://github.com/meshtastic/arduino-fsm.git#2f106146071fc7bc620e1e8d4b88dc4e0266ce39 https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git#31015a55e630a2df77d9d714669c621a5bf355ad - https://github.com/meshtastic/RadioLib.git#8657380241bce681c33aab46598bbf13b11f876c + https://github.com/meshtastic/RadioLib.git#07de964e929238949035fb0d5887026a3058df1a https://github.com/meshtastic/TinyGPSPlus.git#9c1d584d2469523381e077b0b9c1bf868d6c0206 https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460 Wire ; explicitly needed here because the AXP202 library forgets to add it diff --git a/src/configuration.h b/src/configuration.h index dda2b8d0b..460e1a245 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -365,7 +365,7 @@ along with this program. If not, see . #define USE_RF95 #define LORA_DIO0 26 // a No connect on the SX1262 module -#define LORA_RESET 23 +#define LORA_RESET RADIOLIB_NC #define LORA_DIO1 33 // Not really used #define LORA_DIO2 32 // Not really used diff --git a/src/mesh/RF95Interface.h b/src/mesh/RF95Interface.h index 91f5728c5..ebebe3c79 100644 --- a/src/mesh/RF95Interface.h +++ b/src/mesh/RF95Interface.h @@ -14,6 +14,9 @@ class RF95Interface : public RadioLibInterface public: RF95Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, SPIClass &spi); + /// Some boards (Pinetab Lora module) have broken IRQ wires, so we need to poll via i2c registers + bool isIRQPending() { return lora->getPendingIRQ(); } + /// Initialise the Driver transport hardware and software. /// Make sure the Driver is properly configured before calling init(). /// \return true if initialisation succeeded. diff --git a/src/portduino/PortduinoGlue.cpp b/src/portduino/PortduinoGlue.cpp index ce63f8dc4..00513843f 100644 --- a/src/portduino/PortduinoGlue.cpp +++ b/src/portduino/PortduinoGlue.cpp @@ -37,6 +37,52 @@ CryptoEngine *crypto = new CryptoEngine(); void updateBatteryLevel(uint8_t level) NOT_IMPLEMENTED("updateBatteryLevel"); +#include +#include "mesh/RF95Interface.h" + +/** Dear pinetab hardware geeks! + * + * The current pinetab lora module has a slight bug. The ch341 part only provides ISR assertions on edges. + * This makes sense because USB interrupts happen through fast/repeated special irq urbs that are constantly + * chattering on the USB bus. + * + * But this isn't sufficient for level triggered ISR sources like the sx127x radios. The common way that seems to + * be addressed by cs341 users is to **always** connect the INT# (pin 26 on the ch341f) signal to one of the GPIO signals + * on the part. I'd recommend connecting that LORA_DIO0/INT# line to pin 19 (data 4) on the pinetab board. This would + * provide an efficent mechanism so that the (kernel) code in the cs341 driver that I've slightly hacked up to see the + * current state of LORA_DIO0. Without that access, I can't know if the interrupt is still pending - which would create + * race conditions in packet handling. + * + * My workaround is to poll the status register internally to the sx127x. Which is expensive because it involves a number of + * i2c transactions and many trips back and forth between kernel and my userspace app. I think shipping the current version + * of the pinetab lora device would be fine because I can poll slowly (because lora is slow). But if you ever have cause to + * rev this board. I highly encourage this small change. + * + * Btw - your little "USB lora dongle" is really neat. I encourage you to sell it, because even non pinetab customers could + * use it to easily add lora to rasberry pi, desktop pcs etc... + * + * Porduino helper class to do this i2c based polling: + */ +class R595PolledIrqPin : public GPIOPin { +public: + R595PolledIrqPin() : GPIOPin(LORA_DIO0, "LORA_DIO0") {} + + /// Read the low level hardware for this pin + virtual PinStatus readPinHardware() + { + if(isrPinStatus < 0) + return LOW; // No interrupt handler attached, don't bother polling i2c right now + else { + extern RadioInterface *rIf; // FIXME, temporary hack until we know if we need to keep this + + assert(rIf); + RF95Interface *rIf95 = static_cast(rIf); + bool p = rIf95->isIRQPending(); + // log(SysGPIO, LogDebug, "R595PolledIrqPin::readPinHardware(%s, %d, %d)", getName(), getPinNum(), p); + return p ? HIGH : LOW; + } + } +}; /** apps run under portduino can optionally define a portduinoSetup() to @@ -45,7 +91,7 @@ void updateBatteryLevel(uint8_t level) NOT_IMPLEMENTED("updateBatteryLevel"); */ void portduinoSetup() { printf("Setting up Meshtastic on Porduino...\n"); - gpioBind((new SimGPIOPin(LORA_DIO0, "LORA_DIO0"))); - gpioBind((new SimGPIOPin(LORA_RESET, "LORA_RESET"))); + gpioBind(new R595PolledIrqPin()); + // gpioBind((new SimGPIOPin(LORA_RESET, "LORA_RESET"))); gpioBind((new SimGPIOPin(RF95_NSS, "RF95_NSS"))->setSilent()); } From b3ba557b8bcc90795c88ebaefa7409d667a813a5 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 2 Jan 2021 14:14:59 +0800 Subject: [PATCH 07/18] cleanup portuino --- src/portduino/PortduinoGlue.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/portduino/PortduinoGlue.cpp b/src/portduino/PortduinoGlue.cpp index 00513843f..6af006664 100644 --- a/src/portduino/PortduinoGlue.cpp +++ b/src/portduino/PortduinoGlue.cpp @@ -1,9 +1,12 @@ #include "CryptoEngine.h" #include "target_specific.h" #include "PortduinoGPIO.h" -#include +#include "mesh/RF95Interface.h" #include "sleep.h" +#include +#include + // FIXME - move getMacAddr/setBluetoothEnable into a HALPlatform class uint32_t hwId; // fixme move into portduino @@ -37,9 +40,6 @@ CryptoEngine *crypto = new CryptoEngine(); void updateBatteryLevel(uint8_t level) NOT_IMPLEMENTED("updateBatteryLevel"); -#include -#include "mesh/RF95Interface.h" - /** Dear pinetab hardware geeks! * * The current pinetab lora module has a slight bug. The ch341 part only provides ISR assertions on edges. From e627725dfcc9b870ee07f0fe77cc7558bd431e6d Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 2 Jan 2021 14:15:07 +0800 Subject: [PATCH 08/18] 1.1.31 --- version.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.properties b/version.properties index dc155e206..79a74c101 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 1 minor = 1 -build = 30 +build = 31 From a7f93de3ad62914d74bc172290934d60aa01dbe1 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 2 Jan 2021 18:20:51 +0800 Subject: [PATCH 09/18] add a software based cross platform AES-CTR implementation --- platformio.ini | 3 + src/portduino/CrossPlatformCryptoEngine.cpp | 82 +++++++++++++++++++++ src/portduino/PortduinoGlue.cpp | 3 - 3 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 src/portduino/CrossPlatformCryptoEngine.cpp diff --git a/platformio.ini b/platformio.ini index aa8e3eb84..977d2cd55 100644 --- a/platformio.ini +++ b/platformio.ini @@ -314,6 +314,9 @@ src_filter = ${env.src_filter} - - - - build_flags = ${arduino_base.build_flags} -O0 framework = arduino board = linux_x86_64 +lib_deps = + ${arduino_base.lib_deps} + rweather/Crypto ; The GenieBlocks LORA prototype board [env:genieblocks_lora] diff --git a/src/portduino/CrossPlatformCryptoEngine.cpp b/src/portduino/CrossPlatformCryptoEngine.cpp new file mode 100644 index 000000000..b9e818c0b --- /dev/null +++ b/src/portduino/CrossPlatformCryptoEngine.cpp @@ -0,0 +1,82 @@ +#include "AES.h" +#include "CTR.h" +#include "CryptoEngine.h" +#include "configuration.h" + +/** A platform independent AES engine implemented using Tiny-AES + */ +class CrossPlatformCryptoEngine : public CryptoEngine +{ + + CTRCommon *ctr = NULL; + + /// How many bytes in our key + uint8_t keySize = 0; + + public: + CrossPlatformCryptoEngine() {} + + ~CrossPlatformCryptoEngine() {} + + /** + * Set the key used for encrypt, decrypt. + * + * As a special case: If all bytes are zero, we assume _no encryption_ and send all data in cleartext. + * + * @param numBytes must be 16 (AES128), 32 (AES256) or 0 (no crypt) + * @param bytes a _static_ buffer that will remain valid for the life of this crypto instance (i.e. this class will cache the + * provided pointer) + */ + virtual void setKey(size_t numBytes, uint8_t *bytes) + { + keySize = numBytes; + DEBUG_MSG("Installing AES%d key!\n", numBytes * 8); + if (ctr) { + delete ctr; + ctr = NULL; + } + if (numBytes != 0) { + if (numBytes == 16) + ctr = new CTR(); + else + ctr = new CTR(); + + ctr->setKey(bytes, numBytes); + } + } + + /** + * Encrypt a packet + * + * @param bytes is updated in place + */ + virtual void encrypt(uint32_t fromNode, uint64_t packetNum, size_t numBytes, uint8_t *bytes) + { + if (keySize != 0) { + uint8_t stream_block[16]; + static uint8_t scratch[MAX_BLOCKSIZE]; + size_t nc_off = 0; + + // DEBUG_MSG("ESP32 encrypt!\n"); + initNonce(fromNode, packetNum); + assert(numBytes <= MAX_BLOCKSIZE); + memcpy(scratch, bytes, numBytes); + memset(scratch + numBytes, 0, + sizeof(scratch) - numBytes); // Fill rest of buffer with zero (in case cypher looks at it) + + ctr->setIV(nonce, sizeof(nonce)); + ctr->setCounterSize(4); + ctr->encrypt(bytes, scratch, numBytes); + } + } + + virtual void decrypt(uint32_t fromNode, uint64_t packetNum, size_t numBytes, uint8_t *bytes) + { + // For CTR, the implementation is the same + encrypt(fromNode, packetNum, numBytes, bytes); + } + + private: +}; + +CryptoEngine *crypto = new CrossPlatformCryptoEngine(); diff --git a/src/portduino/PortduinoGlue.cpp b/src/portduino/PortduinoGlue.cpp index 6af006664..2d5f0a36c 100644 --- a/src/portduino/PortduinoGlue.cpp +++ b/src/portduino/PortduinoGlue.cpp @@ -35,9 +35,6 @@ void cpuDeepSleep(uint64_t msecs) { notImplemented("cpuDeepSleep"); } -// FIXME - implement real crypto for linux -CryptoEngine *crypto = new CryptoEngine(); - void updateBatteryLevel(uint8_t level) NOT_IMPLEMENTED("updateBatteryLevel"); /** Dear pinetab hardware geeks! From ce4ccf3cc41ba0123ab8bbf8cb6e203c9b2bfeee Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 2 Jan 2021 19:40:24 +0800 Subject: [PATCH 10/18] no need for lora CS control on linux, the spi controller handles it --- src/configuration.h | 2 +- src/portduino/PortduinoGlue.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/configuration.h b/src/configuration.h index cb88ed811..79d1009ca 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -402,7 +402,7 @@ along with this program. If not, see . #define RF95_SCK 5 #define RF95_MISO 19 #define RF95_MOSI 27 -#define RF95_NSS 18 +#define RF95_NSS RADIOLIB_NC // the ch341f spi controller does CS for us #endif diff --git a/src/portduino/PortduinoGlue.cpp b/src/portduino/PortduinoGlue.cpp index 2d5f0a36c..cffaf2e88 100644 --- a/src/portduino/PortduinoGlue.cpp +++ b/src/portduino/PortduinoGlue.cpp @@ -90,5 +90,5 @@ void portduinoSetup() { printf("Setting up Meshtastic on Porduino...\n"); gpioBind(new R595PolledIrqPin()); // gpioBind((new SimGPIOPin(LORA_RESET, "LORA_RESET"))); - gpioBind((new SimGPIOPin(RF95_NSS, "RF95_NSS"))->setSilent()); + // gpioBind((new SimGPIOPin(RF95_NSS, "RF95_NSS"))->setSilent()); } From df21602c90c5767bd18a602bf6895347eb0823eb Mon Sep 17 00:00:00 2001 From: Jm Date: Sat, 2 Jan 2021 10:18:35 -0800 Subject: [PATCH 11/18] Remove text "This interface is experimental" --- src/meshwifi/meshhttp.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index 319a70d7a..7dab845f2 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -559,9 +559,7 @@ void handleStaticBrowse(HTTPRequest *req, HTTPResponse *res) } res->println("

Upload new file

"); - res->println("

*** This interface is experimental ***

"); - res->println("

This form allows you to upload files. Keep your filenames very short and files small. Big filenames and big " - "files (>200k) are a known problem.

"); + res->println("

This form allows you to upload files. Keep your filenames small and files under 200k.

"); res->println("
"); res->println("file:
"); res->println(""); From edd1268f5fffaf60dd2cef179a5b8df936b595f0 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sun, 3 Jan 2021 10:11:20 +0800 Subject: [PATCH 12/18] portduino: begin adding wifi implementation --- src/{esp32 => mesh/wifi}/WiFiServerAPI.cpp | 2 +- src/{esp32 => mesh/wifi}/WiFiServerAPI.h | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{esp32 => mesh/wifi}/WiFiServerAPI.cpp (96%) rename src/{esp32 => mesh/wifi}/WiFiServerAPI.h (100%) diff --git a/src/esp32/WiFiServerAPI.cpp b/src/mesh/wifi/WiFiServerAPI.cpp similarity index 96% rename from src/esp32/WiFiServerAPI.cpp rename to src/mesh/wifi/WiFiServerAPI.cpp index fac955ccc..1f087cc10 100644 --- a/src/esp32/WiFiServerAPI.cpp +++ b/src/mesh/wifi/WiFiServerAPI.cpp @@ -5,7 +5,7 @@ WiFiServerAPI::WiFiServerAPI(WiFiClient &_client) : StreamAPI(&client), client(_client) { - DEBUG_MSG("Incoming connection from %s\n", client.remoteIP().toString().c_str()); + DEBUG_MSG("Incoming wifi connection\n"); } WiFiServerAPI::~WiFiServerAPI() diff --git a/src/esp32/WiFiServerAPI.h b/src/mesh/wifi/WiFiServerAPI.h similarity index 100% rename from src/esp32/WiFiServerAPI.h rename to src/mesh/wifi/WiFiServerAPI.h From 01848a9e5d3d13b8988df0d3f398237b8eba2478 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sun, 3 Jan 2021 20:11:03 +0800 Subject: [PATCH 13/18] moved wifi code --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 977d2cd55..34667d2ca 100644 --- a/platformio.ini +++ b/platformio.ini @@ -183,7 +183,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 = - ${arduino_base.src_filter} - - - + ${arduino_base.src_filter} - - - - lib_ignore = BluetoothOTA monitor_port = /dev/ttyACM1 From 34faea610012fa2455680be8398d901f88f27158 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sun, 3 Jan 2021 20:11:26 +0800 Subject: [PATCH 14/18] fix #622 - we might not have a local position yet early in the boot --- src/plugins/PositionPlugin.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/plugins/PositionPlugin.cpp b/src/plugins/PositionPlugin.cpp index b0ce8e217..e0c77895a 100644 --- a/src/plugins/PositionPlugin.cpp +++ b/src/plugins/PositionPlugin.cpp @@ -31,10 +31,16 @@ MeshPacket *PositionPlugin::allocReply() { NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); assert(node); - assert(node->has_position); + + // We might not have a position yet for our local node, in that case, at least try to send the time + if(!node->has_position) { + memset(&node->position, 0, sizeof(node->position)); + node->has_position = true; + } + + Position &position = node->position; // Update our local node info with our position (even if we don't decide to update anyone else) - auto position = node->position; position.time = getValidTime(RTCQualityGPS); // This nodedb timestamp might be stale, so update it if our clock is valid. return allocDataProtobuf(position); From 3ddae5faec27fb9e6b9c6ecd869c6e4b01e6bae2 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sun, 3 Jan 2021 20:12:31 +0800 Subject: [PATCH 15/18] fix build for esp32 --- 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 54358077a..5ae83f87b 100644 --- a/src/meshwifi/meshwifi.cpp +++ b/src/meshwifi/meshwifi.cpp @@ -1,6 +1,6 @@ #include "meshwifi.h" #include "NodeDB.h" -#include "WiFiServerAPI.h" +#include "mesh/wifi/WiFiServerAPI.h" #include "configuration.h" #include "main.h" #include "meshwifi/meshhttp.h" From da8b1d41c7442612ce6fdd8721cd2cb96735869d Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sun, 3 Jan 2021 20:57:59 +0800 Subject: [PATCH 16/18] 1.1.32 --- version.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.properties b/version.properties index 79a74c101..ac4a03634 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 1 minor = 1 -build = 31 +build = 32 From e9c9e40624881c8be7ef83d972e2cf002bf823c3 Mon Sep 17 00:00:00 2001 From: Jm Date: Mon, 4 Jan 2021 22:15:19 -0800 Subject: [PATCH 17/18] Include instrusctions for real time backtrace decoding. --- docs/software/build-instructions.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/software/build-instructions.md b/docs/software/build-instructions.md index 31008fda0..55ec8d7ad 100644 --- a/docs/software/build-instructions.md +++ b/docs/software/build-instructions.md @@ -39,9 +39,20 @@ cd Meshtastic-device ## Decoding stack traces +### Option 1 + If you get a crash, you can decode the addresses from the `Backtrace:` line: 1. Save the `Backtrace: 0x....` line to a file, e.g., `backtrace.txt`. 2. Run `bin/exception_decoder.py backtrace.txt` (this uses symbols from the last `firmware.elf`, so you must be running the same binary that's still in your `.pio/build` directory). + +### Option 2 + +You can run the exception decoder to monitor the serial output and decode backtraces in real time. + +1. From within PlatformIO, open a new terminal. +2. At the the terminal, enter: + `pio device monitor --port /dev/cu.SLAB_USBtoUART -f esp32_exception_decoder` + Replace the value of port with the location of your serial port. From 84e3d7c27631e937deca2c9faa2afea8d3355f83 Mon Sep 17 00:00:00 2001 From: Jm Date: Tue, 5 Jan 2021 18:57:03 -0800 Subject: [PATCH 18/18] Test fixes for Tobiases --- proto | 2 +- src/meshwifi/meshhttp.cpp | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/proto b/proto index dfe7bc121..75078afe4 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit dfe7bc1217a00c23eecb9dfcf1d56fe95ebddc3b +Subproject commit 75078afe43934f4ce15ef86ebc6950658a170145 diff --git a/src/meshwifi/meshhttp.cpp b/src/meshwifi/meshhttp.cpp index 7dab845f2..f4051dd45 100644 --- a/src/meshwifi/meshhttp.cpp +++ b/src/meshwifi/meshhttp.cpp @@ -494,6 +494,9 @@ void handleStaticBrowse(HTTPRequest *req, HTTPResponse *res) std::string paramValDelete; std::string paramValEdit; + DEBUG_MSG("Static Browse - Disabling keep-alive\n"); + res->setHeader("Connection", "close"); + // Set a default content type res->setHeader("Content-Type", "text/html"); @@ -700,6 +703,11 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res) void handleFormUpload(HTTPRequest *req, HTTPResponse *res) { + + DEBUG_MSG("Form Upload - Disabling keep-alive\n"); + res->setHeader("Connection", "close"); + + DEBUG_MSG("Form Upload - Set frequency to 240mhz\n"); // The upload process is very CPU intensive. Let's speed things up a bit. setCpuFrequencyMhz(240); @@ -708,6 +716,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res) // Then we select the body parser based on the encoding. // Actually we do this only for documentary purposes, we know the form is going // to be multipart/form-data. + DEBUG_MSG("Form Upload - Creating body parser reference\n"); HTTPBodyParser *parser; std::string contentType = req->getHeader("Content-Type"); @@ -723,6 +732,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res) // Now, we can decide based on the content type: if (contentType == "multipart/form-data") { + DEBUG_MSG("Form Upload - multipart/form-data\n"); parser = new HTTPMultipartBodyParser(req); } else { Serial.printf("Unknown POST Content-Type: %s\n", contentType.c_str()); @@ -757,21 +767,21 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res) // Double check that it is what we expect if (name != "file") { - DEBUG_MSG("Skipping unexpected field"); + DEBUG_MSG("Skipping unexpected field\n"); res->println("

No file found.

"); return; } // Double check that it is what we expect if (filename == "") { - DEBUG_MSG("Skipping unexpected field"); + DEBUG_MSG("Skipping unexpected field\n"); res->println("

No file found.

"); return; } // SPIFFS limits the total lenth of a path + file to 31 characters. if (filename.length() + 8 > 31) { - DEBUG_MSG("Uploaded filename too long!"); + DEBUG_MSG("Uploaded filename too long!\n"); res->println("

Uploaded filename too long! Limit of 23 characters.

"); delete parser; return;