From d0451399458314b5160aa8b139bd766ee82451db Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Mon, 16 Nov 2020 07:57:32 +0800 Subject: [PATCH 1/6] return ble errors for invalid values --- src/nimble/BluetoothUtil.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/nimble/BluetoothUtil.cpp b/src/nimble/BluetoothUtil.cpp index 8009f5d22..8a0dd779b 100644 --- a/src/nimble/BluetoothUtil.cpp +++ b/src/nimble/BluetoothUtil.cpp @@ -392,6 +392,7 @@ void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) } } + /** * A helper function that implements simple read and write handling for a uint32_t * @@ -415,6 +416,7 @@ int chr_readwrite32le(uint32_t *v, struct ble_gatt_access_ctxt *ctxt) if (len < sizeof(le)) { DEBUG_MSG("Error: wrongsized write32\n"); *v = 0; + return BLE_ATT_ERR_UNLIKELY; } else { *v = get_le32(le); DEBUG_MSG("BLE writing a uint32\n"); @@ -441,8 +443,10 @@ int chr_readwrite8(uint8_t *v, size_t vlen, struct ble_gatt_access_ctxt *ctxt) auto rc = ble_hs_mbuf_to_flat(ctxt->om, v, vlen, &len); assert(rc == 0); - if (len < vlen) + if (len < vlen) { DEBUG_MSG("Error: wrongsized write\n"); + return BLE_ATT_ERR_UNLIKELY; + } else { DEBUG_MSG("BLE writing bytes\n"); } From f2698bbf91bd9ab1a16f1c9edd337347d164c2f9 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Mon, 16 Nov 2020 08:20:20 +0800 Subject: [PATCH 2/6] bug #496 - allow update clients to program SPIFFS region also have build system properly build spiffs release builds --- bin/build-all.sh | 6 +++++- docs/software/device-api.md | 1 + src/esp32/BluetoothSoftwareUpdate.cpp | 26 +++++++++++++++++++------- src/esp32/BluetoothSoftwareUpdate.h | 3 ++- src/esp32/NimbleSoftwareUpdate.c | 11 ++++++++++- 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/bin/build-all.sh b/bin/build-all.sh index 9f0888f03..a13bfffc9 100755 --- a/bin/build-all.sh +++ b/bin/build-all.sh @@ -87,8 +87,12 @@ platformio lib update do_boards "$BOARDS_ESP32" "false" do_boards "$BOARDS_NRF52" "true" +echo "Building SPIFFS for ESP32 targets" +pio run --environment tbeam -t buildfs +cp .pio/build/tbeam/spiffs.bin $OUTDIR/bins/universal/spiffs-$VERSION.bin + # keep the bins in archive also -cp $OUTDIR/bins/firmware* $OUTDIR/elfs/firmware* $OUTDIR/bins/universal/firmware* $OUTDIR/elfs/universal/firmware* $ARCHIVEDIR +cp $OUTDIR/bins/firmware* $OUTDIR/bins/universal/spiffs* $OUTDIR/elfs/firmware* $OUTDIR/bins/universal/firmware* $OUTDIR/elfs/universal/firmware* $ARCHIVEDIR echo Updating android bins $OUTDIR/forandroid rm -rf $OUTDIR/forandroid diff --git a/docs/software/device-api.md b/docs/software/device-api.md index 031b586a2..cdf9e1368 100644 --- a/docs/software/device-api.md +++ b/docs/software/device-api.md @@ -111,6 +111,7 @@ Characteristics | e272ebac-d463-4b98-bc84-5cc1a39ee517 | write | data, variable sized, recommended 512 bytes, write one for each block of file | | 4826129c-c22a-43a3-b066-ce8f0d5bacc6 | write | crc32, write last - writing this will complete the OTA operation, now you can read result | | 5e134862-7411-4424-ac4a-210937432c77 | read,notify | result code, readable but will notify when the OTA operation completes | +| 5e134862-7411-4424-ac4a-210937432c67 | write | sets the region for programming, currently only 0 (app) or 100 (spiffs) are defined, if not set app is assumed | | GATT_UUID_SW_VERSION_STR/0x2a28 | read | We also implement these standard GATT entries because SW update probably needs them: | | GATT_UUID_MANU_NAME/0x2a29 | read | | | GATT_UUID_HW_VERSION_STR/0x2a27 | read | | diff --git a/src/esp32/BluetoothSoftwareUpdate.cpp b/src/esp32/BluetoothSoftwareUpdate.cpp index 12e30d1ce..03e156b0b 100644 --- a/src/esp32/BluetoothSoftwareUpdate.cpp +++ b/src/esp32/BluetoothSoftwareUpdate.cpp @@ -6,6 +6,7 @@ #include "RadioLibInterface.h" #include "configuration.h" #include "nimble/BluetoothUtil.h" +#include "NodeDB.h" #include #include @@ -16,6 +17,8 @@ static CRC32 crc; static uint32_t rebootAtMsec = 0; // If not zero we will reboot at this time (used to reboot shortly after the update completes) static uint32_t updateExpectedSize, updateActualSize; +static uint8_t update_result; +static uint8_t update_region; static concurrency::Lock *updateLock; @@ -32,8 +35,8 @@ int update_size_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_ crc.reset(); if (Update.isRunning()) Update.abort(); - bool canBegin = Update.begin(updateExpectedSize); - DEBUG_MSG("Setting update size %u, result %d\n", updateExpectedSize, canBegin); + bool canBegin = Update.begin(updateExpectedSize, update_region); + DEBUG_MSG("Setting region %d update size %u, result %d\n", update_region, updateExpectedSize, canBegin); if (!canBegin) { // Indicate failure by forcing the size to 0 (client will read it back) updateExpectedSize = 0; @@ -72,13 +75,11 @@ int update_data_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_ crc.update(data, len); Update.write(data, len); updateActualSize += len; - powerFSM.trigger(EVENT_CONTACT_FROM_PHONE); + powerFSM.trigger(EVENT_CONTACT_FROM_PHONE); return 0; } -static uint8_t update_result; - /// Handle writes to crc32 int update_crc32_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { @@ -100,8 +101,14 @@ int update_crc32_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble result = 0xe0; // FIXME, use real error codes } else { if (Update.end()) { - DEBUG_MSG("OTA done, rebooting in 5 seconds!\n"); - rebootAtMsec = millis() + 5000; + if (update_region == U_SPIFFS) { + DEBUG_MSG("SPIFFS updated!\n"); + nodeDB.saveToDisk(); // Since we just wiped spiffs, we need to save our current state + } + else { + DEBUG_MSG("Appload updated, rebooting in 5 seconds!\n"); + rebootAtMsec = millis() + 5000; + } } else { DEBUG_MSG("Error Occurred. Error #: %d\n", Update.getError()); } @@ -125,6 +132,11 @@ int update_result_callback(uint16_t conn_handle, uint16_t attr_handle, struct bl return chr_readwrite8(&update_result, sizeof(update_result), ctxt); } +int update_region_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) +{ + return chr_readwrite8(&update_region, sizeof(update_region), ctxt); +} + void bluetoothRebootCheck() { if (rebootAtMsec && millis() > rebootAtMsec) { diff --git a/src/esp32/BluetoothSoftwareUpdate.h b/src/esp32/BluetoothSoftwareUpdate.h index c7a412d69..f5e1a1ded 100644 --- a/src/esp32/BluetoothSoftwareUpdate.h +++ b/src/esp32/BluetoothSoftwareUpdate.h @@ -14,10 +14,11 @@ int update_size_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_ int update_data_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); int update_result_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); int update_crc32_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); +int update_region_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); extern const struct ble_gatt_svc_def gatt_update_svcs[]; -extern const ble_uuid128_t update_result_uuid; +extern const ble_uuid128_t update_result_uuid, update_region_uuid; extern int16_t updateResultHandle; diff --git a/src/esp32/NimbleSoftwareUpdate.c b/src/esp32/NimbleSoftwareUpdate.c index e02cd4a9d..956fdf53f 100644 --- a/src/esp32/NimbleSoftwareUpdate.c +++ b/src/esp32/NimbleSoftwareUpdate.c @@ -23,6 +23,10 @@ const ble_uuid128_t update_crc32_uuid = const ble_uuid128_t update_result_uuid = BLE_UUID128_INIT(0x77, 0x2c, 0x43, 0x37, 0x09, 0x21, 0x4a, 0xac, 0x24, 0x44, 0x11, 0x74, 0x62, 0x48, 0x13, 0x5e); +// "5e134862-7411-4424-ac4a-210937432c67" write +const ble_uuid128_t update_region_uuid = + BLE_UUID128_INIT(0x67, 0x2c, 0x43, 0x37, 0x09, 0x21, 0x4a, 0xac, 0x24, 0x44, 0x11, 0x74, 0x62, 0x48, 0x13, 0x5e); + const struct ble_gatt_svc_def gatt_update_svcs[] = { { /*** Service: Security test. */ @@ -47,9 +51,14 @@ const struct ble_gatt_svc_def gatt_update_svcs[] = { }, { .uuid = &update_result_uuid.u, - .access_cb = update_size_callback, + .access_cb = update_result_callback, .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_NOTIFY, }, + { + .uuid = &update_region_uuid.u, + .access_cb = update_region_callback, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_AUTHEN, + }, { 0, /* No more characteristics in this service. */ }}, From df75cefeeb608691452426c5da9c788bba82a303 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Wed, 18 Nov 2020 10:35:13 +0800 Subject: [PATCH 3/6] fix #525 - turn off (buggy) TinyGPS custom candidates support --- platformio.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index c33784cfe..4f73d1955 100644 --- a/platformio.ini +++ b/platformio.ini @@ -31,6 +31,7 @@ build_flags = -Wno-missing-field-initializers -Isrc -Isrc/mesh -Isrc/gps -Ilib/n -DAPP_VERSION=${sysenv.APP_VERSION} -DHW_VERSION=${sysenv.HW_VERSION} -DUSE_THREAD_NAMES + -DTINYGPSPLUS_OPTION_NO_CUSTOM_FIELDS ; leave this commented out to avoid breaking Windows ;upload_port = /dev/ttyUSB0 @@ -64,7 +65,7 @@ lib_deps = 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/TinyGPSPlus.git + 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 SPI From d7d13d637c005edc7b60eeca06f08bc3c71a7f46 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Thu, 19 Nov 2020 09:25:02 +0800 Subject: [PATCH 4/6] clean up filesystem goo, add spiffs to install scripts, fix #496 @mc-hamster seems to work pretty good for me, so I'll send a PR to you for the dev-http branch. I'll push out an android alpha build later today (once the build is complete). Once this new device load is out in the field _future_ device builds will support updating spiffs from android. (i.e. device loads older than 1.1.9 must be updated to 1.1.9 or later before spiffs support is implemented on the device side - so some users might need to update twice before the new spiffs contents will appear on their device) --- bin/build-all.sh | 4 ++-- bin/device-install.sh | 3 +++ src/FSCommon.cpp | 21 +++++++++++++++++++++ src/FSCommon.h | 29 +++++++++++++++++++++++++++++ src/main.cpp | 19 +++++++++++-------- src/mesh/NodeDB.cpp | 29 ++--------------------------- 6 files changed, 68 insertions(+), 37 deletions(-) create mode 100644 src/FSCommon.cpp create mode 100644 src/FSCommon.h diff --git a/bin/build-all.sh b/bin/build-all.sh index a13bfffc9..ab779e187 100755 --- a/bin/build-all.sh +++ b/bin/build-all.sh @@ -9,7 +9,7 @@ COUNTRIES="US EU433 EU865 CN JP ANZ KR" #COUNTRIES=CN BOARDS_ESP32="tlora-v2 tlora-v1 tlora-v2-1-1.6 tbeam heltec tbeam0.7" -# BOARDS_ESP32=tbeam +#BOARDS_ESP32=tbeam # FIXME note nrf52840dk build is for some reason only generating a BIN file but not a HEX file nrf52840dk-geeksville is fine BOARDS_NRF52="lora-relay-v1" @@ -113,6 +113,6 @@ XML echo Generating $ARCHIVEDIR/firmware-$VERSION.zip rm -f $ARCHIVEDIR/firmware-$VERSION.zip -zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $OUTDIR/bins/firmware-*-$VERSION.* images/system-info.bin bin/device-install.sh bin/device-update.sh +zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $ARCHIVEDIR/spiffs-$VERSION.bin $OUTDIR/bins/firmware-*-$VERSION.* images/system-info.bin bin/device-install.sh bin/device-update.sh echo BUILT ALL diff --git a/bin/device-install.sh b/bin/device-install.sh index fb374d091..3d5f27af8 100755 --- a/bin/device-install.sh +++ b/bin/device-install.sh @@ -1,5 +1,7 @@ #!/bin/sh +set -e + # Usage info show_help() { cat << EOF @@ -36,6 +38,7 @@ if [ -f "${FILENAME}" ]; then echo "Trying to flash ${FILENAME}, but first erasing and writing system information" esptool.py --baud 921600 erase_flash esptool.py --baud 921600 write_flash 0x1000 system-info.bin + esptool.py --baud 921600 write_flash 0x00390000 spiffs-*.bin esptool.py --baud 921600 write_flash 0x10000 ${FILENAME} else echo "Invalid file: ${FILENAME}" diff --git a/src/FSCommon.cpp b/src/FSCommon.cpp new file mode 100644 index 000000000..2ce7f0bbe --- /dev/null +++ b/src/FSCommon.cpp @@ -0,0 +1,21 @@ +#include "FSCommon.h" + +void fsInit() +{ +#ifdef FS + if (!FSBegin()) + { + DEBUG_MSG("ERROR filesystem mount Failed\n"); + assert(0); // FIXME - report failure to phone + } + + DEBUG_MSG("Filesystem files:\n"); + File dir = FS.open("/"); + File f = dir.openNextFile(); + while (f) { + DEBUG_MSG(" %s\n", f.name()); + f.close(); + f = dir.openNextFile(); + } +#endif +} diff --git a/src/FSCommon.h b/src/FSCommon.h new file mode 100644 index 000000000..a1adb952e --- /dev/null +++ b/src/FSCommon.h @@ -0,0 +1,29 @@ +#pragma once + +#include "configuration.h" + +// Cross platform filesystem API + +#ifdef PORTDUINO +// Portduino version +#include "PortduinoFS.h" +#define FS PortduinoFS +#define FSBegin() true +#define FILE_O_WRITE "w" +#define FILE_O_READ "r" +#elif !defined(NO_ESP32) +// ESP32 version +#include "SPIFFS.h" +#define FS SPIFFS +#define FSBegin() FS.begin(true) +#define FILE_O_WRITE "w" +#define FILE_O_READ "r" +#else +// NRF52 version +#include "InternalFileSystem.h" +#define FS InternalFS +#define FSBegin() FS.begin() +using namespace Adafruit_LittleFS_Namespace; +#endif + +void fsInit(); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 61bb2be14..33b60d843 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,6 +11,7 @@ // #include "rom/rtc.h" #include "DSRRouter.h" // #include "debug.h" +#include "FSCommon.h" #include "RTC.h" #include "SPILock.h" #include "concurrency/OSThread.h" @@ -173,7 +174,7 @@ class ButtonThread : public OSThread #ifdef BUTTON_PIN userButton = OneButton(BUTTON_PIN, true, true); #ifdef INPUT_PULLUP_SENSE - // Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did + // Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did pinMode(BUTTON_PIN, INPUT_PULLUP_SENSE); #endif userButton.attachClick(userButtonPressed); @@ -184,9 +185,9 @@ class ButtonThread : public OSThread #ifdef BUTTON_PIN_ALT userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true); #ifdef INPUT_PULLUP_SENSE - // Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did + // Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did pinMode(BUTTON_PIN_ALT, INPUT_PULLUP_SENSE); -#endif +#endif userButtonAlt.attachClick(userButtonPressed); userButtonAlt.attachDuringLongPress(userButtonPressedLong); userButtonAlt.attachDoubleClick(userButtonDoublePressed); @@ -209,7 +210,7 @@ class ButtonThread : public OSThread canSleep &= userButtonAlt.isIdle(); #endif // if (!canSleep) DEBUG_MSG("Supressing sleep!\n"); - //else DEBUG_MSG("sleep ok\n"); + // else DEBUG_MSG("sleep ok\n"); return 5; } @@ -225,13 +226,13 @@ class ButtonThread : public OSThread DEBUG_MSG("Long press!\n"); screen->adjustBrightness(); } - + static void userButtonDoublePressed() -{ + { #ifndef NO_ESP32 - disablePin(); + disablePin(); #endif -} + } }; static Periodic *ledPeriodic; @@ -266,6 +267,8 @@ void setup() ledPeriodic = new Periodic("Blink", ledBlinker); + fsInit(); + router = new DSRRouter(); #ifdef I2C_SDA diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 61be815ec..517845b9b 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -16,6 +16,7 @@ #include "error.h" #include "mesh-pb-constants.h" #include "meshwifi/meshwifi.h" +#include "FSCommon.h" #include #include @@ -35,27 +36,7 @@ DeviceState versions used to be defined in the .proto file but really only this #define DEVICESTATE_CUR_VER 11 #define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER -#ifdef PORTDUINO -// Portduino version -#include "PortduinoFS.h" -#define FS PortduinoFS -#define FSBegin() true -#define FILE_O_WRITE "w" -#define FILE_O_READ "r" -#elif !defined(NO_ESP32) -// ESP32 version -#include "SPIFFS.h" -#define FS SPIFFS -#define FSBegin() FS.begin(true) -#define FILE_O_WRITE "w" -#define FILE_O_READ "r" -#else -// NRF52 version -#include "InternalFileSystem.h" -#define FS InternalFS -#define FSBegin() FS.begin() -using namespace Adafruit_LittleFS_Namespace; -#endif + // FIXME - move this somewhere else extern void getMacAddr(uint8_t *dmac); @@ -210,12 +191,6 @@ void NodeDB::init() { installDefaultDeviceState(); - if (!FSBegin()) // FIXME - do this in main? - { - DEBUG_MSG("ERROR filesystem mount Failed\n"); - assert(0); // FIXME - report failure to phone - } - // saveToDisk(); loadFromDisk(); // saveToDisk(); From 19d81347f289cc573bd2fcf1b4c5c8ba2e8b479a Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Fri, 20 Nov 2020 07:42:02 +0800 Subject: [PATCH 5/6] 1.1.9 (release for @mc-hamster only in android app alpha) --- bin/version.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/version.sh b/bin/version.sh index 8a7fb3ca3..2e7677737 100644 --- a/bin/version.sh +++ b/bin/version.sh @@ -1,3 +1,3 @@ -export VERSION=1.1.8 \ No newline at end of file +export VERSION=1.1.9 \ No newline at end of file From c427c8abf95daa8ce1e7c930a133088ca819347c Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 28 Nov 2020 08:55:56 +0800 Subject: [PATCH 6/6] oops - fix my crummy merge --- src/main.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index e0c1dbc16..78c1bee16 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -250,6 +250,18 @@ class ButtonThread : public OSThread disablePin(); #endif } + + static void userButtonPressedLongStart() + { + DEBUG_MSG("Long press start!\n"); + longPressTime = millis(); + } + + static void userButtonPressedLongStop() + { + DEBUG_MSG("Long press stop!\n"); + longPressTime = 0; + } }; static Periodic *ledPeriodic;