From c5180d4588b226f91933f6f2d31f312b610d6346 Mon Sep 17 00:00:00 2001 From: taco Date: Tue, 29 Jul 2025 20:06:35 +1000 Subject: [PATCH 1/6] initial commit: CustomLFS --- examples/companion_radio/DataStore.cpp | 23 ++++++++++++++------ examples/companion_radio/main.cpp | 30 ++++++++++++++++++++++++-- platformio.ini | 4 ++++ src/helpers/IdentityStore.h | 21 +++++++++++++----- variants/xiao_nrf52/platformio.ini | 3 ++- 5 files changed, 66 insertions(+), 15 deletions(-) diff --git a/examples/companion_radio/DataStore.cpp b/examples/companion_radio/DataStore.cpp index b5d70edc..8e774d91 100644 --- a/examples/companion_radio/DataStore.cpp +++ b/examples/companion_radio/DataStore.cpp @@ -1,6 +1,12 @@ #include #include "DataStore.h" +#if defined(EXTRAFS) || defined(SPIFLASH) + #define MAX_BLOBRECS 100 +#else + #define MAX_BLOBRECS 20 +#endif + DataStore::DataStore(FILESYSTEM& fs, mesh::RTCClock& clock) : _fs(&fs), _clock(&clock), #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) identity_store(fs, "") @@ -41,7 +47,9 @@ void DataStore::begin() { #elif defined(RP2040_PLATFORM) #include #elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) - #include + // #include // disabled for now, leaving here for dual fs branch + #include + #include #endif #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) @@ -51,9 +59,9 @@ int _countLfsBlock(void *p, lfs_block_t block){ return 0; } -lfs_ssize_t _getLfsUsedBlockCount() { +lfs_ssize_t _getLfsUsedBlockCount(FILESYSTEM* fs) { lfs_size_t size = 0; - lfs_traverse(InternalFS._getFS(), _countLfsBlock, &size); + lfs_traverse(fs->_getFS(), _countLfsBlock, &size); return size; } #endif @@ -67,8 +75,8 @@ uint32_t DataStore::getStorageUsedKb() const { _fs->info(info); return info.usedBytes / 1024; #elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) - const lfs_config* config = InternalFS._getFS()->cfg; - int usedBlockCount = _getLfsUsedBlockCount(); + const lfs_config* config = _fs->_getFS()->cfg; + int usedBlockCount = _getLfsUsedBlockCount(_fs); int usedBytes = config->block_size * usedBlockCount; return usedBytes / 1024; #else @@ -85,7 +93,7 @@ uint32_t DataStore::getStorageTotalKb() const { _fs->info(info); return info.totalBytes / 1024; #elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) - const lfs_config* config = InternalFS._getFS()->cfg; + const lfs_config* config = _fs->_getFS()->cfg; int totalBytes = config->block_size * config->block_count; return totalBytes / 1024; #else @@ -109,6 +117,7 @@ bool DataStore::removeFile(const char* filename) { bool DataStore::formatFileSystem() { #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) + // InternalFS.format(); // leaving as placeholder to remind for dual fs branch return _fs->format(); #elif defined(RP2040_PLATFORM) return LittleFS.format(); @@ -336,7 +345,7 @@ void DataStore::checkAdvBlobFile() { if (file) { BlobRec zeroes; memset(&zeroes, 0, sizeof(zeroes)); - for (int i = 0; i < 20; i++) { // pre-allocate to fixed size + for (int i = 0; i < MAX_BLOBRECS; i++) { // pre-allocate to fixed size file.write((uint8_t *) &zeroes, sizeof(zeroes)); } file.close(); diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 1d5ec564..4900d3bc 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -14,7 +14,20 @@ static uint32_t _atoi(const char* sp) { #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) #include - DataStore store(InternalFS, rtc_clock); + #if defined(SPIFLASH) + #include + const int chipSelect = PIN_QSPI_CS; + SPIClass SPI_2(NRF_SPIM2, PIN_QSPI_IO1, PIN_QSPI_SCK, PIN_QSPI_IO0); + DataStore store(FlashFS, rtc_clock); + #else + #if defined(EXTRAFS) + #include + CustomLFS ExtraFS(0xD4000, 0x19000, 128); + DataStore store(ExtraFS, rtc_clock); + #else + DataStore store(InternalFS, rtc_clock); + #endif + #endif #elif defined(RP2040_PLATFORM) #include DataStore store(LittleFS, rtc_clock); @@ -23,6 +36,7 @@ static uint32_t _atoi(const char* sp) { DataStore store(SPIFFS, rtc_clock); #endif + #ifdef ESP32 #ifdef WIFI_SSID #include @@ -117,7 +131,19 @@ void setup() { fast_rng.begin(radio_get_rng_seed()); #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) - InternalFS.begin(); + #if defined(SPIFLASH) + if (!FlashFS.begin(chipSelect, SPI_2)) { + // debug output might not be available at this point, might be too early. maybe should fall back to InternalFS here? + MESH_DEBUG_PRINTLN("CustomLFS_SPIFlash: failed to initialize"); + } else { + MESH_DEBUG_PRINTLN("CustomLFS_SPIFlash: initialized successfully"); + } + #else + InternalFS.begin(); + #if defined(EXTRAFS) + ExtraFS.begin(); + #endif + #endif store.begin(); the_mesh.begin( #ifdef DISPLAY_CLASS diff --git a/platformio.ini b/platformio.ini index 1c89465f..5fe46986 100644 --- a/platformio.ini +++ b/platformio.ini @@ -78,6 +78,10 @@ platform = nordicnrf52 build_flags = ${arduino_base.build_flags} -D NRF52_PLATFORM -D LFS_NO_ASSERT=1 + -D EXTRAFS=1 +lib_deps = + ${arduino_base.lib_deps} + https://github.com/oltaco/CustomLFS ; ----------------- RP2040 --------------------- diff --git a/src/helpers/IdentityStore.h b/src/helpers/IdentityStore.h index e81290e7..15219a44 100644 --- a/src/helpers/IdentityStore.h +++ b/src/helpers/IdentityStore.h @@ -4,12 +4,19 @@ #include #define FILESYSTEM fs::FS #elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) - #include - #define FILESYSTEM Adafruit_LittleFS + #if defined(SPIFLASH) + #include + #define FILESYSTEM CustomLFS_SPIFlash + #elif defined(EXTRAFS) + #include + #define FILESYSTEM CustomLFS + #else + #include + #define FILESYSTEM Adafruit_LittleFS - using namespace Adafruit_LittleFS_Namespace; + using namespace Adafruit_LittleFS_Namespace; + #endif #endif - #include class IdentityStore { @@ -18,7 +25,11 @@ class IdentityStore { public: IdentityStore(FILESYSTEM& fs, const char* dir): _fs(&fs), _dir(dir) { } - void begin() { if (_dir && _dir[0] == '/') { _fs->mkdir(_dir); } } + void begin() { + if (_dir && _dir[0] == '/') { _fs->mkdir(_dir); } + + + } bool load(const char *name, mesh::LocalIdentity& id); bool load(const char *name, mesh::LocalIdentity& id, char display_name[], int max_name_sz); bool save(const char *name, const mesh::LocalIdentity& id); diff --git a/variants/xiao_nrf52/platformio.ini b/variants/xiao_nrf52/platformio.ini index fd4c362b..3717c26d 100644 --- a/variants/xiao_nrf52/platformio.ini +++ b/variants/xiao_nrf52/platformio.ini @@ -65,7 +65,8 @@ build_flags = -D OFFLINE_QUEUE_SIZE=256 ; -D BLE_DEBUG_LOGGING=1 ; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 + -D MESH_DEBUG=1 + -D SPIFLASH=1 build_src_filter = ${Xiao_nrf52.build_src_filter} + +<../examples/companion_radio/*.cpp> From bdfe9ad27bffcf4e9566c0e561048a38ebd3174e Mon Sep 17 00:00:00 2001 From: taco Date: Sat, 2 Aug 2025 08:31:23 +1000 Subject: [PATCH 2/6] switch to using QSPI bus for external flash --- examples/companion_radio/DataStore.cpp | 6 ++++-- examples/companion_radio/main.cpp | 16 +++++++--------- src/helpers/IdentityStore.h | 6 +++--- variants/nano_g2_ultra/platformio.ini | 1 + variants/thinknode_m1/platformio.ini | 1 + variants/thinknode_m1/variant.h | 9 +++++++++ variants/wio-tracker-l1/platformio.ini | 1 + variants/xiao_nrf52/platformio.ini | 2 +- 8 files changed, 27 insertions(+), 15 deletions(-) diff --git a/examples/companion_radio/DataStore.cpp b/examples/companion_radio/DataStore.cpp index 8e774d91..8c2962d3 100644 --- a/examples/companion_radio/DataStore.cpp +++ b/examples/companion_radio/DataStore.cpp @@ -1,7 +1,7 @@ #include #include "DataStore.h" -#if defined(EXTRAFS) || defined(SPIFLASH) +#if defined(EXTRAFS) || defined(QSPIFLASH) #define MAX_BLOBRECS 100 #else #define MAX_BLOBRECS 20 @@ -49,7 +49,9 @@ void DataStore::begin() { #elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) // #include // disabled for now, leaving here for dual fs branch #include - #include + #if defined(QSPIFLASH) + #include + #endif #endif #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 4900d3bc..2dca708d 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -14,11 +14,9 @@ static uint32_t _atoi(const char* sp) { #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) #include - #if defined(SPIFLASH) - #include - const int chipSelect = PIN_QSPI_CS; - SPIClass SPI_2(NRF_SPIM2, PIN_QSPI_IO1, PIN_QSPI_SCK, PIN_QSPI_IO0); - DataStore store(FlashFS, rtc_clock); + #if defined(QSPIFLASH) + #include + DataStore store(QSPIFlash, rtc_clock); #else #if defined(EXTRAFS) #include @@ -131,12 +129,12 @@ void setup() { fast_rng.begin(radio_get_rng_seed()); #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) - #if defined(SPIFLASH) - if (!FlashFS.begin(chipSelect, SPI_2)) { + #if defined(QSPIFLASH) + if (!QSPIFlash.begin()) { // debug output might not be available at this point, might be too early. maybe should fall back to InternalFS here? - MESH_DEBUG_PRINTLN("CustomLFS_SPIFlash: failed to initialize"); + MESH_DEBUG_PRINTLN("CustomLFS_QSPIFlash: failed to initialize"); } else { - MESH_DEBUG_PRINTLN("CustomLFS_SPIFlash: initialized successfully"); + MESH_DEBUG_PRINTLN("CustomLFS_QSPIFlash: initialized successfully"); } #else InternalFS.begin(); diff --git a/src/helpers/IdentityStore.h b/src/helpers/IdentityStore.h index 15219a44..99c2bd77 100644 --- a/src/helpers/IdentityStore.h +++ b/src/helpers/IdentityStore.h @@ -4,9 +4,9 @@ #include #define FILESYSTEM fs::FS #elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) - #if defined(SPIFLASH) - #include - #define FILESYSTEM CustomLFS_SPIFlash + #if defined(QSPIFLASH) + #include + #define FILESYSTEM CustomLFS_QSPIFlash #elif defined(EXTRAFS) #include #define FILESYSTEM CustomLFS diff --git a/variants/nano_g2_ultra/platformio.ini b/variants/nano_g2_ultra/platformio.ini index 7fb2de28..e70c353b 100644 --- a/variants/nano_g2_ultra/platformio.ini +++ b/variants/nano_g2_ultra/platformio.ini @@ -42,6 +42,7 @@ build_flags = -D OFFLINE_QUEUE_SIZE=256 -D DISPLAY_CLASS=SH1106Display -D PIN_BUZZER=4 + -D QSPIFLASH=1 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${Nano_G2_Ultra.build_src_filter} diff --git a/variants/thinknode_m1/platformio.ini b/variants/thinknode_m1/platformio.ini index e29e1471..eadc83ae 100644 --- a/variants/thinknode_m1/platformio.ini +++ b/variants/thinknode_m1/platformio.ini @@ -80,6 +80,7 @@ build_flags = -D OFFLINE_QUEUE_SIZE=256 -D PIN_BUZZER=6 -D AUTO_SHUTDOWN_MILLIVOLTS=3300 + -D QSPIFLASH=1 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${ThinkNode_M1.build_src_filter} diff --git a/variants/thinknode_m1/variant.h b/variants/thinknode_m1/variant.h index 2b58e341..f7f52a6a 100644 --- a/variants/thinknode_m1/variant.h +++ b/variants/thinknode_m1/variant.h @@ -110,6 +110,15 @@ extern const int MISO; extern const int MOSI; extern const int SCK; +//////////////////////////////////////////////////////////////////////////////// +// QSPI +#define PIN_QSPI_SCK (46) +#define PIN_QSPI_CS (47) +#define PIN_QSPI_IO0 (44) // MOSI if using two bit interface +#define PIN_QSPI_IO1 (45) // MISO if using two bit interface +#define PIN_QSPI_IO2 (7) // WP if using two bit interface (i.e. not used) +#define PIN_QSPI_IO3 (5) // HOLD if using two bit interface (i.e. not used) + //////////////////////////////////////////////////////////////////////////////// // Display diff --git a/variants/wio-tracker-l1/platformio.ini b/variants/wio-tracker-l1/platformio.ini index be0086c4..02f09e5c 100644 --- a/variants/wio-tracker-l1/platformio.ini +++ b/variants/wio-tracker-l1/platformio.ini @@ -86,6 +86,7 @@ build_flags = ${WioTrackerL1.build_flags} -D OFFLINE_QUEUE_SIZE=256 -D DISPLAY_CLASS=SH1106Display -D PIN_BUZZER=12 + -D QSPIFLASH=1 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${WioTrackerL1.build_src_filter} diff --git a/variants/xiao_nrf52/platformio.ini b/variants/xiao_nrf52/platformio.ini index 3717c26d..3e181672 100644 --- a/variants/xiao_nrf52/platformio.ini +++ b/variants/xiao_nrf52/platformio.ini @@ -66,7 +66,7 @@ build_flags = ; -D BLE_DEBUG_LOGGING=1 ; -D MESH_PACKET_LOGGING=1 -D MESH_DEBUG=1 - -D SPIFLASH=1 + -D QSPIFLASH=1 build_src_filter = ${Xiao_nrf52.build_src_filter} + +<../examples/companion_radio/*.cpp> From 2b24c575c7dbf77bc322d0155ef3493291780199 Mon Sep 17 00:00:00 2001 From: taco Date: Fri, 22 Aug 2025 13:09:54 +1000 Subject: [PATCH 3/6] support dual filsystems on nrf52 store identity and prefs in UserData and contacts, channels and adv_blobs in ExtraData --- examples/companion_radio/DataStore.cpp | 212 +++++++++++++++++++++++-- examples/companion_radio/DataStore.h | 7 + examples/companion_radio/MyMesh.cpp | 60 ++++++- examples/companion_radio/main.cpp | 10 +- src/helpers/IdentityStore.h | 8 - 5 files changed, 268 insertions(+), 29 deletions(-) diff --git a/examples/companion_radio/DataStore.cpp b/examples/companion_radio/DataStore.cpp index 8c2962d3..ca7337bd 100644 --- a/examples/companion_radio/DataStore.cpp +++ b/examples/companion_radio/DataStore.cpp @@ -18,14 +18,28 @@ DataStore::DataStore(FILESYSTEM& fs, mesh::RTCClock& clock) : _fs(&fs), _clock(& { } -static File openWrite(FILESYSTEM* _fs, const char* filename) { +#if defined(EXTRAFS) || defined(QSPIFLASH) + +DataStore::DataStore(FILESYSTEM& fs, FILESYSTEM& fsExtra, mesh::RTCClock& clock) : _fs(&fs), _fsExtra(&fsExtra), _clock(&clock), #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) - _fs->remove(filename); - return _fs->open(filename, FILE_O_WRITE); + identity_store(fs, "") #elif defined(RP2040_PLATFORM) - return _fs->open(filename, "w"); + identity_store(fs, "/identity") #else - return _fs->open(filename, "w", true); + identity_store(fs, "/identity") +#endif +{ +} +#endif + +static File openWrite(FILESYSTEM* fs, const char* filename) { +#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) + fs->remove(filename); + return fs->open(filename, FILE_O_WRITE); +#elif defined(RP2040_PLATFORM) + return fs->open(filename, "w"); +#else + return fs->open(filename, "w", true); #endif } @@ -36,6 +50,9 @@ void DataStore::begin() { #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) checkAdvBlobFile(); + #if defined(EXTRAFS) || defined(QSPIFLASH) + migrateToSecondaryFS(); + #endif #else // init 'blob store' support _fs->mkdir("/bl"); @@ -46,12 +63,13 @@ void DataStore::begin() { #include #elif defined(RP2040_PLATFORM) #include -#elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) - // #include // disabled for now, leaving here for dual fs branch +#elif defined(NRF52_PLATFORM) #include #if defined(QSPIFLASH) #include #endif +#elif defined(STM32_PLATFORM) + #include #endif #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) @@ -77,8 +95,13 @@ uint32_t DataStore::getStorageUsedKb() const { _fs->info(info); return info.usedBytes / 1024; #elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) +#if defined(EXTRAFS) || defined(QSPIFLASH) + const lfs_config* config = _fsExtra->_getFS()->cfg; + int usedBlockCount = _getLfsUsedBlockCount(_fsExtra); +#else const lfs_config* config = _fs->_getFS()->cfg; int usedBlockCount = _getLfsUsedBlockCount(_fs); +#endif int usedBytes = config->block_size * usedBlockCount; return usedBytes / 1024; #else @@ -95,7 +118,11 @@ uint32_t DataStore::getStorageTotalKb() const { _fs->info(info); return info.totalBytes / 1024; #elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) +#if defined(EXTRAFS) || defined(QSPIFLASH) + const lfs_config* config = _fsExtra->_getFS()->cfg; +#else const lfs_config* config = _fs->_getFS()->cfg; +#endif int totalBytes = config->block_size * config->block_count; return totalBytes / 1024; #else @@ -113,14 +140,31 @@ File DataStore::openRead(const char* filename) { #endif } +File DataStore::openRead(FILESYSTEM* fs, const char* filename) { +#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) + return fs->open(filename, FILE_O_READ); +#elif defined(RP2040_PLATFORM) + return fs->open(filename, "r"); +#else + return fs->open(filename, "r", false); +#endif +} + bool DataStore::removeFile(const char* filename) { return _fs->remove(filename); } +bool DataStore::removeFile(FILESYSTEM* fs, const char* filename) { + return fs->remove(filename); +} + bool DataStore::formatFileSystem() { #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) - // InternalFS.format(); // leaving as placeholder to remind for dual fs branch +#if defined(EXTRAFS) || defined(QSPIFLASH) + return _fs->format() && _fsExtra->format(); // in future maybe return an error code based on which format failed? +#else return _fs->format(); +#endif #elif defined(RP2040_PLATFORM) return LittleFS.format(); #elif defined(ESP32) @@ -214,11 +258,20 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_ } void DataStore::loadContacts(DataStoreHost* host) { +#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) +#if defined(EXTRAFS) || defined(QSPIFLASH) + if (_fsExtra->exists("/contacts3")) { + File file = _fsExtra->open("/contacts3"); +#else if (_fs->exists("/contacts3")) { -#if defined(RP2040_PLATFORM) + File file = _fs->open("/contacts3"); +#endif +#elif defined(RP2040_PLATFORM) + if (_fs->exists("/contacts3")) { File file = _fs->open("/contacts3", "r"); #else - File file = _fs->open("/contacts3"); + if (_fs->exists("/contacts3")) { + File file = _fs->open("/contacts3", "r", false); #endif if (file) { bool full = false; @@ -251,7 +304,11 @@ void DataStore::loadContacts(DataStoreHost* host) { } void DataStore::saveContacts(DataStoreHost* host) { +#if defined(EXTRAFS) || defined(QSPIFLASH) + File file = openWrite(_fsExtra, "/contacts3"); +#else File file = openWrite(_fs, "/contacts3"); +#endif if (file) { uint32_t idx = 0; ContactInfo c; @@ -280,11 +337,20 @@ void DataStore::saveContacts(DataStoreHost* host) { } void DataStore::loadChannels(DataStoreHost* host) { +#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) +#if defined(EXTRAFS) || defined(QSPIFLASH) + if (_fsExtra->exists("/channels2")) { + File file = _fsExtra->open("/channels2"); +#else + if (_fs->exists("/channels2")) { + File file = _fs->open("/channels2"); +#endif +#elif defined(RP2040_PLATFORM) if (_fs->exists("/channels2")) { -#if defined(RP2040_PLATFORM) File file = _fs->open("/channels2", "r"); #else - File file = _fs->open("/channels2"); + if (_fs->exists("/channels2")) { + File file = _fs->open("/channels2", "r", false); #endif if (file) { bool full = false; @@ -311,7 +377,11 @@ void DataStore::loadChannels(DataStoreHost* host) { } void DataStore::saveChannels(DataStoreHost* host) { +#if defined(EXTRAFS) || defined(QSPIFLASH) + File file = openWrite(_fsExtra, "/channels2"); +#else File file = openWrite(_fs, "/channels2"); +#endif if (file) { uint8_t channel_idx = 0; ChannelDetails ch; @@ -342,8 +412,13 @@ struct BlobRec { }; void DataStore::checkAdvBlobFile() { +#if defined(EXTRAFS) || defined(QSPIFLASH) + if (!_fsExtra->exists("/adv_blobs")) { + File file = openWrite(_fsExtra, "/adv_blobs"); +#else if (!_fs->exists("/adv_blobs")) { File file = openWrite(_fs, "/adv_blobs"); +#endif if (file) { BlobRec zeroes; memset(&zeroes, 0, sizeof(zeroes)); @@ -355,8 +430,117 @@ void DataStore::checkAdvBlobFile() { } } +void DataStore::migrateToSecondaryFS() { + // migrate old adv_blobs, contacts3 and channels2 files to secondary FS if they don't already exist + if (!_fsExtra->exists("/adv_blobs")) { + if (_fs->exists("/adv_blobs")) { + File oldAdvBlobs = openRead(_fs, "/adv_blobs"); + File newAdvBlobs = openWrite(_fsExtra, "/adv_blobs"); + + if (oldAdvBlobs && newAdvBlobs) { + BlobRec rec; + size_t count = 0; + + // Copy 20 BlobRecs from old to new + while (count < 20 && oldAdvBlobs.read((uint8_t *)&rec, sizeof(rec)) == sizeof(rec)) { + newAdvBlobs.seek(count * sizeof(BlobRec)); + newAdvBlobs.write((uint8_t *)&rec, sizeof(rec)); + count++; + } + } + if (oldAdvBlobs) oldAdvBlobs.close(); + if (newAdvBlobs) newAdvBlobs.close(); + _fs->remove("/adv_blobs"); + } + } + if (!_fsExtra->exists("/contacts3")) { + if (_fs->exists("/contacts3")) { + File oldFile = openRead(_fs, "/contacts3"); + File newFile = openWrite(_fsExtra, "/contacts3"); + + if (oldFile && newFile) { + uint8_t buf[64]; + int n; + while ((n = oldFile.read(buf, sizeof(buf))) > 0) { + newFile.write(buf, n); + } + } + if (oldFile) oldFile.close(); + if (newFile) newFile.close(); + _fs->remove("/contacts3"); + } + } + if (!_fsExtra->exists("/channels2")) { + if (_fs->exists("/contacts2")) { + File oldFile = openRead(_fs, "/contacts2"); + File newFile = openWrite(_fsExtra, "/contacts2"); + + if (oldFile && newFile) { + uint8_t buf[64]; + int n; + while ((n = oldFile.read(buf, sizeof(buf))) > 0) { + newFile.write(buf, n); + } + } + if (oldFile) oldFile.close(); + if (newFile) newFile.close(); + _fs->remove("/contacts2"); + } + } + // cleanup nodes which have been testing the extra fs, copy _main.id and new_prefs back to primary + if (_fsExtra->exists("/_main.id")) { + if (_fs->exists("/_main.id")) {_fs->remove("/_main.id");} + File oldFile = openRead(_fsExtra, "/_main.id"); + File newFile = openWrite(_fs, "/_main.id"); + + if (oldFile && newFile) { + uint8_t buf[64]; + int n; + while ((n = oldFile.read(buf, sizeof(buf))) > 0) { + newFile.write(buf, n); + } + } + if (oldFile) oldFile.close(); + if (newFile) newFile.close(); + _fsExtra->remove("/_main.id"); + } + if (_fsExtra->exists("/new_prefs")) { + if (_fs->exists("/new_prefs")) {_fs->remove("/new_prefs");} + File oldFile = openRead(_fsExtra, "/new_prefs"); + File newFile = openWrite(_fs, "/new_prefs"); + + if (oldFile && newFile) { + uint8_t buf[64]; + int n; + while ((n = oldFile.read(buf, sizeof(buf))) > 0) { + newFile.write(buf, n); + } + } + if (oldFile) oldFile.close(); + if (newFile) newFile.close(); + _fsExtra->remove("/new_prefs"); + } + // remove files from where they should not be anymore + if (_fs->exists("/adv_blobs")) { + _fs->remove("/adv_blobs"); + } + if (_fs->exists("/contacts3")) { + _fs->remove("/contacts3"); + } + if (_fsExtra->exists("/_main.id")) { + _fsExtra->remove("/_main.id"); + } + if (_fsExtra->exists("/new_prefs")) { + _fsExtra->remove("/new_prefs"); + } +} + uint8_t DataStore::getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]) { +#if defined(EXTRAFS) || defined(QSPIFLASH) + File file = _fsExtra->open("/adv_blobs"); +#else File file = _fs->open("/adv_blobs"); +#endif uint8_t len = 0; // 0 = not found if (file) { @@ -378,7 +562,11 @@ bool DataStore::putBlobByKey(const uint8_t key[], int key_len, const uint8_t src checkAdvBlobFile(); +#if defined(EXTRAFS) || defined(QSPIFLASH) + File file = _fsExtra->open("/adv_blobs", FILE_O_WRITE); +#else File file = _fs->open("/adv_blobs", FILE_O_WRITE); +#endif if (file) { uint32_t pos = 0, found_pos = 0; uint32_t min_timestamp = 0xFFFFFFFF; diff --git a/examples/companion_radio/DataStore.h b/examples/companion_radio/DataStore.h index 7bd33301..04579bb3 100644 --- a/examples/companion_radio/DataStore.h +++ b/examples/companion_radio/DataStore.h @@ -15,6 +15,7 @@ public: class DataStore { FILESYSTEM* _fs; + FILESYSTEM* _fsExtra; mesh::RTCClock* _clock; IdentityStore identity_store; @@ -25,8 +26,11 @@ class DataStore { public: DataStore(FILESYSTEM& fs, mesh::RTCClock& clock); + DataStore(FILESYSTEM& fs, FILESYSTEM& fsExtra, mesh::RTCClock& clock); void begin(); bool formatFileSystem(); + FILESYSTEM* getPrimaryFS() const { return _fs; } + FILESYSTEM* getSecondaryFS() const { return _fsExtra; } bool loadMainIdentity(mesh::LocalIdentity &identity); bool saveMainIdentity(const mesh::LocalIdentity &identity); void loadPrefs(NodePrefs& prefs, double& node_lat, double& node_lon); @@ -35,10 +39,13 @@ public: void saveContacts(DataStoreHost* host); void loadChannels(DataStoreHost* host); void saveChannels(DataStoreHost* host); + void migrateToSecondaryFS(); uint8_t getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]); bool putBlobByKey(const uint8_t key[], int key_len, const uint8_t src_buf[], uint8_t len); File openRead(const char* filename); + File openRead(FILESYSTEM* fs, const char* filename); bool removeFile(const char* filename); + bool removeFile(FILESYSTEM* fs, const char* filename); uint32_t getStorageUsedKb() const; uint32_t getStorageTotalKb() const; }; diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index 1fa5478b..6d4339b0 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -1530,27 +1530,65 @@ void MyMesh::checkCLIRescueCmd() { if(root){ File file = root.openNextFile(); while (file) { - + + #if defined(EXTRAFS) || defined(QSPIFLASH) + if (file.isDirectory()) { + Serial.printf("[dir] /FS1/%s\n", file.name()); + } else { + Serial.printf("[file] /FS1/%s (%d bytes)\n", file.name(), file.size()); + } + #else if (file.isDirectory()) { Serial.printf("[dir] %s\n", file.name()); } else { Serial.printf("[file] %s (%d bytes)\n", file.name(), file.size()); } - + #endif // move to next file file = root.openNextFile(); } root.close(); } + #if defined(EXTRAFS) || defined(QSPIFLASH) + root = _store->openRead(_store->getSecondaryFS(), path); + if(root){ + File file = root.openNextFile(); + while (file) { + + if (file.isDirectory()) { + Serial.printf("[dir] /FS2/%s\n", file.name()); + } else { + Serial.printf("[file] /FS2/%s (%d bytes)\n", file.name(), file.size()); + } + + // move to next file + file = root.openNextFile(); + + } + root.close(); + } + #endif } else if (memcmp(cli_command, "cat", 3) == 0) { // get path from command e.g: "cat /contacts3" const char *path = &cli_command[4]; + // + bool is_fs2 = false; + if (memcmp(path, "FS1/", 4) == 0) { + path += 3; // skip "FS1" + } else if (memcmp(path, "FS2/", 4) == 0) { + path += 3; // skip "FS2" + is_fs2 = true; + } + // log file content as hex File file = _store->openRead(path); + if (is_fs2 == true) { + file = _store->openRead(_store->getSecondaryFS(), path); + } if(file){ // get file content @@ -1570,14 +1608,28 @@ void MyMesh::checkCLIRescueCmd() { // get path from command e.g: "rm /adv_blobs" const char *path = &cli_command[4]; - + MESH_DEBUG_PRINTLN("Removing file: %s", path); // ensure path is not empty, or root dir if(!path || strlen(path) == 0 || strcmp(path, "/") == 0){ Serial.println("Invalid path provided"); } else { + bool is_fs2 = false; + if (memcmp(path, "FS1/", 4) == 0) { + path += 3; // skip "FS1" + } else if (memcmp(path, "FS2/", 4) == 0) { + path += 3; // skip "FS2" + is_fs2 = true; + } // remove file - bool removed = _store->removeFile(path); + bool removed; + if (is_fs2) { + MESH_DEBUG_PRINTLN("Removing file from FS2: %s", path); + removed = _store->removeFile(_store->getSecondaryFS(), path); + } else { + MESH_DEBUG_PRINTLN("Removing file from FS1: %s", path); + removed = _store->removeFile(path); + } if(removed){ Serial.println("File removed"); } else { diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 2dca708d..9651c301 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -16,12 +16,12 @@ static uint32_t _atoi(const char* sp) { #include #if defined(QSPIFLASH) #include - DataStore store(QSPIFlash, rtc_clock); + DataStore store(InternalFS, QSPIFlash, rtc_clock); #else #if defined(EXTRAFS) #include CustomLFS ExtraFS(0xD4000, 0x19000, 128); - DataStore store(ExtraFS, rtc_clock); + DataStore store(InternalFS, ExtraFS, rtc_clock); #else DataStore store(InternalFS, rtc_clock); #endif @@ -129,6 +129,7 @@ void setup() { fast_rng.begin(radio_get_rng_seed()); #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) + InternalFS.begin(); #if defined(QSPIFLASH) if (!QSPIFlash.begin()) { // debug output might not be available at this point, might be too early. maybe should fall back to InternalFS here? @@ -137,10 +138,9 @@ void setup() { MESH_DEBUG_PRINTLN("CustomLFS_QSPIFlash: initialized successfully"); } #else - InternalFS.begin(); - #if defined(EXTRAFS) + #if defined(EXTRAFS) ExtraFS.begin(); - #endif + #endif #endif store.begin(); the_mesh.begin( diff --git a/src/helpers/IdentityStore.h b/src/helpers/IdentityStore.h index 99c2bd77..e022696a 100644 --- a/src/helpers/IdentityStore.h +++ b/src/helpers/IdentityStore.h @@ -4,18 +4,10 @@ #include #define FILESYSTEM fs::FS #elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) - #if defined(QSPIFLASH) - #include - #define FILESYSTEM CustomLFS_QSPIFlash - #elif defined(EXTRAFS) - #include - #define FILESYSTEM CustomLFS - #else #include #define FILESYSTEM Adafruit_LittleFS using namespace Adafruit_LittleFS_Namespace; - #endif #endif #include From accd1e0a97c5b6725b9d7653bfe084d42322a963 Mon Sep 17 00:00:00 2001 From: taco Date: Mon, 25 Aug 2025 12:41:59 +1000 Subject: [PATCH 4/6] nrf52 targets: increase limits for contacts and channels --- examples/companion_radio/DataStore.cpp | 22 ++++++++++++++-------- examples/companion_radio/main.cpp | 1 - platformio.ini | 2 +- src/helpers/IdentityStore.h | 11 ++++------- variants/heltec_mesh_solar/platformio.ini | 8 ++++---- variants/heltec_t114/platformio.ini | 8 ++++---- variants/ikoka_stick_nrf/platformio.ini | 8 ++++---- variants/lilygo_techo/platformio.ini | 5 +++-- variants/minewsemi_me25ls01/platformio.ini | 8 ++++---- variants/nano_g2_ultra/platformio.ini | 8 ++++---- variants/promicro/platformio.ini | 8 ++++---- variants/rak4631/platformio.ini | 8 ++++---- variants/sensecap_solar/platformio.ini | 8 ++++---- variants/t1000-e/platformio.ini | 4 ++-- variants/thinknode_m1/platformio.ini | 4 ++-- variants/wio-tracker-l1/platformio.ini | 4 ++-- variants/xiao_nrf52/platformio.ini | 8 ++++---- 17 files changed, 64 insertions(+), 61 deletions(-) diff --git a/examples/companion_radio/DataStore.cpp b/examples/companion_radio/DataStore.cpp index ca7337bd..a27c4c86 100644 --- a/examples/companion_radio/DataStore.cpp +++ b/examples/companion_radio/DataStore.cpp @@ -63,13 +63,16 @@ void DataStore::begin() { #include #elif defined(RP2040_PLATFORM) #include -#elif defined(NRF52_PLATFORM) - #include +#elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) #if defined(QSPIFLASH) #include + #else + #if defined(EXTRAFS) + #include + #else + #include #endif -#elif defined(STM32_PLATFORM) - #include +#endif #endif #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) @@ -471,9 +474,9 @@ void DataStore::migrateToSecondaryFS() { } } if (!_fsExtra->exists("/channels2")) { - if (_fs->exists("/contacts2")) { - File oldFile = openRead(_fs, "/contacts2"); - File newFile = openWrite(_fsExtra, "/contacts2"); + if (_fs->exists("/channels2")) { + File oldFile = openRead(_fs, "/channels2"); + File newFile = openWrite(_fsExtra, "/channels2"); if (oldFile && newFile) { uint8_t buf[64]; @@ -484,7 +487,7 @@ void DataStore::migrateToSecondaryFS() { } if (oldFile) oldFile.close(); if (newFile) newFile.close(); - _fs->remove("/contacts2"); + _fs->remove("/channels2"); } } // cleanup nodes which have been testing the extra fs, copy _main.id and new_prefs back to primary @@ -527,6 +530,9 @@ void DataStore::migrateToSecondaryFS() { if (_fs->exists("/contacts3")) { _fs->remove("/contacts3"); } + if (_fs->exists("/channels2")) { + _fs->remove("/channels2"); + } if (_fsExtra->exists("/_main.id")) { _fsExtra->remove("/_main.id"); } diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 9651c301..89adca59 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -34,7 +34,6 @@ static uint32_t _atoi(const char* sp) { DataStore store(SPIFFS, rtc_clock); #endif - #ifdef ESP32 #ifdef WIFI_SSID #include diff --git a/platformio.ini b/platformio.ini index 5fe46986..c08cd853 100644 --- a/platformio.ini +++ b/platformio.ini @@ -81,7 +81,7 @@ build_flags = ${arduino_base.build_flags} -D EXTRAFS=1 lib_deps = ${arduino_base.lib_deps} - https://github.com/oltaco/CustomLFS + https://github.com/oltaco/CustomLFS @ 0.2 ; ----------------- RP2040 --------------------- diff --git a/src/helpers/IdentityStore.h b/src/helpers/IdentityStore.h index e022696a..d0d7ee45 100644 --- a/src/helpers/IdentityStore.h +++ b/src/helpers/IdentityStore.h @@ -4,10 +4,10 @@ #include #define FILESYSTEM fs::FS #elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) - #include - #define FILESYSTEM Adafruit_LittleFS + #include + #define FILESYSTEM Adafruit_LittleFS - using namespace Adafruit_LittleFS_Namespace; + using namespace Adafruit_LittleFS_Namespace; #endif #include @@ -18,10 +18,7 @@ public: IdentityStore(FILESYSTEM& fs, const char* dir): _fs(&fs), _dir(dir) { } void begin() { - if (_dir && _dir[0] == '/') { _fs->mkdir(_dir); } - - - } + if (_dir && _dir[0] == '/') { _fs->mkdir(_dir); } } bool load(const char *name, mesh::LocalIdentity& id); bool load(const char *name, mesh::LocalIdentity& id, char display_name[], int max_name_sz); bool save(const char *name, const mesh::LocalIdentity& id); diff --git a/variants/heltec_mesh_solar/platformio.ini b/variants/heltec_mesh_solar/platformio.ini index 9fd3edd5..18c4ac73 100644 --- a/variants/heltec_mesh_solar/platformio.ini +++ b/variants/heltec_mesh_solar/platformio.ini @@ -59,8 +59,8 @@ build_flags = extends = Heltec_mesh_solar build_flags = ${Heltec_mesh_solar.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 -D BLE_PIN_CODE=123456 ; -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 @@ -77,8 +77,8 @@ lib_deps = extends = Heltec_mesh_solar build_flags = ${Heltec_mesh_solar.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 ; -D BLE_PIN_CODE=123456 ; -D BLE_DEBUG_LOGGING=1 ; -D MESH_PACKET_LOGGING=1 diff --git a/variants/heltec_t114/platformio.ini b/variants/heltec_t114/platformio.ini index 2cac2eae..7222bb11 100644 --- a/variants/heltec_t114/platformio.ini +++ b/variants/heltec_t114/platformio.ini @@ -74,8 +74,8 @@ extends = Heltec_t114 build_flags = ${Heltec_t114.build_flags} -I examples/companion_radio/ui-new - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 -D BLE_PIN_CODE=123456 ; -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 @@ -94,8 +94,8 @@ extends = Heltec_t114 build_flags = ${Heltec_t114.build_flags} -I examples/companion_radio/ui-new - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 ; -D BLE_PIN_CODE=123456 ; -D BLE_DEBUG_LOGGING=1 ; -D MESH_PACKET_LOGGING=1 diff --git a/variants/ikoka_stick_nrf/platformio.ini b/variants/ikoka_stick_nrf/platformio.ini index 6e6ae101..1f2bbfe9 100644 --- a/variants/ikoka_stick_nrf/platformio.ini +++ b/variants/ikoka_stick_nrf/platformio.ini @@ -103,8 +103,8 @@ build_src_filter = ${nrf52840_xiao.build_src_filter} extends = ikoka_stick_nrf_baseboard build_flags = ${ikoka_stick_nrf_baseboard.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 -D BLE_PIN_CODE=123456 -D OFFLINE_QUEUE_SIZE=256 -I examples/companion_radio/ui-new @@ -123,8 +123,8 @@ lib_deps = extends = ikoka_stick_nrf_baseboard build_flags = ${ikoka_stick_nrf_baseboard.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 -I examples/companion_radio/ui-new ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 diff --git a/variants/lilygo_techo/platformio.ini b/variants/lilygo_techo/platformio.ini index 8a090a4d..91223205 100644 --- a/variants/lilygo_techo/platformio.ini +++ b/variants/lilygo_techo/platformio.ini @@ -82,8 +82,9 @@ build_flags = ${LilyGo_T-Echo.build_flags} -I src/helpers/ui -I examples/companion_radio/ui-new - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 + -D QSPIFLASH=1 -D BLE_PIN_CODE=123456 ; -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 diff --git a/variants/minewsemi_me25ls01/platformio.ini b/variants/minewsemi_me25ls01/platformio.ini index 3436062f..71887002 100644 --- a/variants/minewsemi_me25ls01/platformio.ini +++ b/variants/minewsemi_me25ls01/platformio.ini @@ -52,8 +52,8 @@ lib_deps = ${nrf52840_me25ls01.lib_deps} extends = me25ls01 build_flags = ${me25ls01.build_flags} -I examples/companion_radio/ui-orig - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 -D BLE_PIN_CODE=123456 ; -D BLE_DEBUG_LOGGING=1 -D MESH_PACKET_LOGGING=1 @@ -149,8 +149,8 @@ lib_deps = ${me25ls01.lib_deps} extends = me25ls01 build_flags = ${me25ls01.build_flags} -I examples/companion_radio/ui-orig - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 ;-D BLE_PIN_CODE=123456 ; -D BLE_DEBUG_LOGGING=1 -D MESH_PACKET_LOGGING=1 diff --git a/variants/nano_g2_ultra/platformio.ini b/variants/nano_g2_ultra/platformio.ini index e70c353b..163f4311 100644 --- a/variants/nano_g2_ultra/platformio.ini +++ b/variants/nano_g2_ultra/platformio.ini @@ -35,8 +35,8 @@ build_flags = ${Nano_G2_Ultra.build_flags} -I src/helpers/ui -I examples/companion_radio/ui-new - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 -D BLE_PIN_CODE=123456 ; -D BLE_DEBUG_LOGGING=0 -D OFFLINE_QUEUE_SIZE=256 @@ -66,8 +66,8 @@ build_flags = ${Nano_G2_Ultra.build_flags} -I src/helpers/ui -I examples/companion_radio/ui-new - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 -D OFFLINE_QUEUE_SIZE=256 -D DISPLAY_CLASS=SH1106Display -D PIN_BUZZER=4 diff --git a/variants/promicro/platformio.ini b/variants/promicro/platformio.ini index 6b77bdcf..5a70f7ba 100644 --- a/variants/promicro/platformio.ini +++ b/variants/promicro/platformio.ini @@ -88,8 +88,8 @@ lib_deps = ${Faketec.lib_deps} extends = Faketec build_flags = ${Faketec.build_flags} -I examples/companion_radio/ui-new - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 -D DISPLAY_CLASS=SSD1306Display ; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 ; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 @@ -106,8 +106,8 @@ lib_deps = ${Faketec.lib_deps} extends = Faketec build_flags = ${Faketec.build_flags} -I examples/companion_radio/ui-new - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 -D BLE_PIN_CODE=123456 -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini index c9091878..7e7d2234 100644 --- a/variants/rak4631/platformio.ini +++ b/variants/rak4631/platformio.ini @@ -70,8 +70,8 @@ build_flags = -D PIN_USER_BTN=9 -D PIN_USER_BTN_ANA=31 -D DISPLAY_CLASS=SSD1306Display - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 ; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 ; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 build_src_filter = ${rak4631.build_src_filter} @@ -89,8 +89,8 @@ build_flags = -D PIN_USER_BTN=9 -D PIN_USER_BTN_ANA=31 -D DISPLAY_CLASS=SSD1306Display - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 -D BLE_PIN_CODE=123456 -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 diff --git a/variants/sensecap_solar/platformio.ini b/variants/sensecap_solar/platformio.ini index bbac5d99..649ace84 100644 --- a/variants/sensecap_solar/platformio.ini +++ b/variants/sensecap_solar/platformio.ini @@ -76,8 +76,8 @@ build_src_filter = ${SenseCap_Solar.build_src_filter} extends = SenseCap_Solar build_flags = ${SenseCap_Solar.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 -D BLE_PIN_CODE=123456 -D OFFLINE_QUEUE_SIZE=256 ; -D BLE_DEBUG_LOGGING=1 @@ -94,8 +94,8 @@ lib_deps = extends = SenseCap_Solar build_flags = ${SenseCap_Solar.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${SenseCap_Solar.build_src_filter} diff --git a/variants/t1000-e/platformio.ini b/variants/t1000-e/platformio.ini index 044fffd8..d7b43cce 100644 --- a/variants/t1000-e/platformio.ini +++ b/variants/t1000-e/platformio.ini @@ -91,8 +91,8 @@ lib_deps = ${t1000-e.lib_deps} extends = t1000-e build_flags = ${t1000-e.build_flags} -I examples/companion_radio/ui-orig - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 -D BLE_PIN_CODE=123456 ; -D BLE_DEBUG_LOGGING=1 ; -D MESH_PACKET_LOGGING=1 diff --git a/variants/thinknode_m1/platformio.ini b/variants/thinknode_m1/platformio.ini index eadc83ae..a530d259 100644 --- a/variants/thinknode_m1/platformio.ini +++ b/variants/thinknode_m1/platformio.ini @@ -71,8 +71,8 @@ build_flags = ${ThinkNode_M1.build_flags} -I src/helpers/ui -I examples/companion_radio/ui-new - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 -D BLE_PIN_CODE=123456 -D BLE_DEBUG_LOGGING=1 -D DISPLAY_ROTATION=4 diff --git a/variants/wio-tracker-l1/platformio.ini b/variants/wio-tracker-l1/platformio.ini index 02f09e5c..87670bd0 100644 --- a/variants/wio-tracker-l1/platformio.ini +++ b/variants/wio-tracker-l1/platformio.ini @@ -79,8 +79,8 @@ lib_deps = ${WioTrackerL1.lib_deps} extends = WioTrackerL1 build_flags = ${WioTrackerL1.build_flags} -I examples/companion_radio/ui-new - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 -D BLE_PIN_CODE=123456 -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 diff --git a/variants/xiao_nrf52/platformio.ini b/variants/xiao_nrf52/platformio.ini index 3e181672..10807476 100644 --- a/variants/xiao_nrf52/platformio.ini +++ b/variants/xiao_nrf52/platformio.ini @@ -59,8 +59,8 @@ upload_protocol = nrfutil extends = Xiao_nrf52 build_flags = ${Xiao_nrf52.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 -D BLE_PIN_CODE=123456 -D OFFLINE_QUEUE_SIZE=256 ; -D BLE_DEBUG_LOGGING=1 @@ -78,8 +78,8 @@ lib_deps = extends = Xiao_nrf52 build_flags = ${Xiao_nrf52.build_flags} - -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=8 + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${Xiao_nrf52.build_src_filter} From 3d8355682995ca56be9cd2d6fdc7986f85daf09b Mon Sep 17 00:00:00 2001 From: taco Date: Sat, 6 Sep 2025 14:07:18 +1000 Subject: [PATCH 5/6] refactor: use _getContactsChannelsFS() instead of ifdefs --- examples/companion_radio/DataStore.cpp | 86 ++++++-------------------- examples/companion_radio/DataStore.h | 3 + 2 files changed, 23 insertions(+), 66 deletions(-) diff --git a/examples/companion_radio/DataStore.cpp b/examples/companion_radio/DataStore.cpp index a27c4c86..7631b905 100644 --- a/examples/companion_radio/DataStore.cpp +++ b/examples/companion_radio/DataStore.cpp @@ -7,7 +7,7 @@ #define MAX_BLOBRECS 20 #endif -DataStore::DataStore(FILESYSTEM& fs, mesh::RTCClock& clock) : _fs(&fs), _clock(&clock), +DataStore::DataStore(FILESYSTEM& fs, mesh::RTCClock& clock) : _fs(&fs), _fsExtra(nullptr), _clock(&clock), #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) identity_store(fs, "") #elif defined(RP2040_PLATFORM) @@ -19,7 +19,6 @@ DataStore::DataStore(FILESYSTEM& fs, mesh::RTCClock& clock) : _fs(&fs), _clock(& } #if defined(EXTRAFS) || defined(QSPIFLASH) - DataStore::DataStore(FILESYSTEM& fs, FILESYSTEM& fsExtra, mesh::RTCClock& clock) : _fs(&fs), _fsExtra(&fsExtra), _clock(&clock), #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) identity_store(fs, "") @@ -66,14 +65,12 @@ void DataStore::begin() { #elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) #if defined(QSPIFLASH) #include - #else - #if defined(EXTRAFS) + #elif defined(EXTRAFS) #include #else #include #endif #endif -#endif #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) int _countLfsBlock(void *p, lfs_block_t block){ @@ -98,13 +95,8 @@ uint32_t DataStore::getStorageUsedKb() const { _fs->info(info); return info.usedBytes / 1024; #elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) -#if defined(EXTRAFS) || defined(QSPIFLASH) - const lfs_config* config = _fsExtra->_getFS()->cfg; - int usedBlockCount = _getLfsUsedBlockCount(_fsExtra); -#else - const lfs_config* config = _fs->_getFS()->cfg; - int usedBlockCount = _getLfsUsedBlockCount(_fs); -#endif + const lfs_config* config = _getContactsChannelsFS()->_getFS()->cfg; + int usedBlockCount = _getLfsUsedBlockCount(_getContactsChannelsFS()); int usedBytes = config->block_size * usedBlockCount; return usedBytes / 1024; #else @@ -121,11 +113,7 @@ uint32_t DataStore::getStorageTotalKb() const { _fs->info(info); return info.totalBytes / 1024; #elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) -#if defined(EXTRAFS) || defined(QSPIFLASH) - const lfs_config* config = _fsExtra->_getFS()->cfg; -#else - const lfs_config* config = _fs->_getFS()->cfg; -#endif + const lfs_config* config = _getContactsChannelsFS()->_getFS()->cfg; int totalBytes = config->block_size * config->block_count; return totalBytes / 1024; #else @@ -163,11 +151,11 @@ bool DataStore::removeFile(FILESYSTEM* fs, const char* filename) { bool DataStore::formatFileSystem() { #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) -#if defined(EXTRAFS) || defined(QSPIFLASH) - return _fs->format() && _fsExtra->format(); // in future maybe return an error code based on which format failed? -#else - return _fs->format(); -#endif + if (_fsExtra == nullptr) { + return _fs->format(); + } else { + return _fs->format() && _fsExtra->format(); + } #elif defined(RP2040_PLATFORM) return LittleFS.format(); #elif defined(ESP32) @@ -262,13 +250,8 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_ void DataStore::loadContacts(DataStoreHost* host) { #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) -#if defined(EXTRAFS) || defined(QSPIFLASH) - if (_fsExtra->exists("/contacts3")) { - File file = _fsExtra->open("/contacts3"); -#else - if (_fs->exists("/contacts3")) { - File file = _fs->open("/contacts3"); -#endif + if (_getContactsChannelsFS()->exists("/contacts3")) { + File file = _getContactsChannelsFS()->open("/contacts3"); #elif defined(RP2040_PLATFORM) if (_fs->exists("/contacts3")) { File file = _fs->open("/contacts3", "r"); @@ -307,11 +290,7 @@ void DataStore::loadContacts(DataStoreHost* host) { } void DataStore::saveContacts(DataStoreHost* host) { -#if defined(EXTRAFS) || defined(QSPIFLASH) - File file = openWrite(_fsExtra, "/contacts3"); -#else - File file = openWrite(_fs, "/contacts3"); -#endif + File file = openWrite(_getContactsChannelsFS(), "/contacts3"); if (file) { uint32_t idx = 0; ContactInfo c; @@ -341,13 +320,8 @@ void DataStore::saveContacts(DataStoreHost* host) { void DataStore::loadChannels(DataStoreHost* host) { #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) -#if defined(EXTRAFS) || defined(QSPIFLASH) - if (_fsExtra->exists("/channels2")) { - File file = _fsExtra->open("/channels2"); -#else - if (_fs->exists("/channels2")) { - File file = _fs->open("/channels2"); -#endif + if (_getContactsChannelsFS()->exists("/channels2")) { + File file = _getContactsChannelsFS()->open("/channels2"); #elif defined(RP2040_PLATFORM) if (_fs->exists("/channels2")) { File file = _fs->open("/channels2", "r"); @@ -380,11 +354,7 @@ void DataStore::loadChannels(DataStoreHost* host) { } void DataStore::saveChannels(DataStoreHost* host) { -#if defined(EXTRAFS) || defined(QSPIFLASH) - File file = openWrite(_fsExtra, "/channels2"); -#else - File file = openWrite(_fs, "/channels2"); -#endif + File file = openWrite(_getContactsChannelsFS(), "/channels2"); if (file) { uint8_t channel_idx = 0; ChannelDetails ch; @@ -415,13 +385,8 @@ struct BlobRec { }; void DataStore::checkAdvBlobFile() { -#if defined(EXTRAFS) || defined(QSPIFLASH) - if (!_fsExtra->exists("/adv_blobs")) { - File file = openWrite(_fsExtra, "/adv_blobs"); -#else - if (!_fs->exists("/adv_blobs")) { - File file = openWrite(_fs, "/adv_blobs"); -#endif + if (!_getContactsChannelsFS()->exists("/adv_blobs")) { + File file = openWrite(_getContactsChannelsFS(), "/adv_blobs"); if (file) { BlobRec zeroes; memset(&zeroes, 0, sizeof(zeroes)); @@ -542,13 +507,8 @@ void DataStore::migrateToSecondaryFS() { } uint8_t DataStore::getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]) { -#if defined(EXTRAFS) || defined(QSPIFLASH) - File file = _fsExtra->open("/adv_blobs"); -#else - File file = _fs->open("/adv_blobs"); -#endif + File file = _getContactsChannelsFS()->open("/adv_blobs"); uint8_t len = 0; // 0 = not found - if (file) { BlobRec tmp; while (file.read((uint8_t *) &tmp, sizeof(tmp)) == sizeof(tmp)) { @@ -565,14 +525,8 @@ uint8_t DataStore::getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_b bool DataStore::putBlobByKey(const uint8_t key[], int key_len, const uint8_t src_buf[], uint8_t len) { if (len < PUB_KEY_SIZE+4+SIGNATURE_SIZE || len > MAX_ADVERT_PKT_LEN) return false; - checkAdvBlobFile(); - -#if defined(EXTRAFS) || defined(QSPIFLASH) - File file = _fsExtra->open("/adv_blobs", FILE_O_WRITE); -#else - File file = _fs->open("/adv_blobs", FILE_O_WRITE); -#endif + File file = _getContactsChannelsFS()->open("/adv_blobs", FILE_O_WRITE); if (file) { uint32_t pos = 0, found_pos = 0; uint32_t min_timestamp = 0xFFFFFFFF; diff --git a/examples/companion_radio/DataStore.h b/examples/companion_radio/DataStore.h index 04579bb3..62580942 100644 --- a/examples/companion_radio/DataStore.h +++ b/examples/companion_radio/DataStore.h @@ -48,4 +48,7 @@ public: bool removeFile(FILESYSTEM* fs, const char* filename); uint32_t getStorageUsedKb() const; uint32_t getStorageTotalKb() const; + +private: + FILESYSTEM* _getContactsChannelsFS() const { if (_fsExtra) return _fsExtra; return _fs;}; }; From bcfc8d37711ec76e1e51a05a34b5026a69a48b2a Mon Sep 17 00:00:00 2001 From: taco Date: Sat, 6 Sep 2025 14:09:05 +1000 Subject: [PATCH 6/6] improved RescueCLI for dual FS --- examples/companion_radio/MyMesh.cpp | 100 ++++++++++++++-------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index 6d4339b0..7847d652 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -1524,64 +1524,65 @@ void MyMesh::checkCLIRescueCmd() { // get path from command e.g: "ls /adafruit" const char *path = &cli_command[3]; - + + bool is_fs2 = false; + if (memcmp(path, "UserData/", 9) == 0) { + path += 8; // skip "UserData" + } else if (memcmp(path, "ExtraFS/", 8) == 0) { + path += 7; // skip "ExtraFS" + is_fs2 = true; + } + Serial.printf("Listing files in %s\n", path); + // log each file and directory File root = _store->openRead(path); - if(root){ - File file = root.openNextFile(); - while (file) { - - #if defined(EXTRAFS) || defined(QSPIFLASH) - if (file.isDirectory()) { - Serial.printf("[dir] /FS1/%s\n", file.name()); - } else { - Serial.printf("[file] /FS1/%s (%d bytes)\n", file.name(), file.size()); - } - #else - if (file.isDirectory()) { - Serial.printf("[dir] %s\n", file.name()); - } else { - Serial.printf("[file] %s (%d bytes)\n", file.name(), file.size()); - } - #endif - // move to next file - file = root.openNextFile(); - - } - root.close(); - } - #if defined(EXTRAFS) || defined(QSPIFLASH) - root = _store->openRead(_store->getSecondaryFS(), path); - if(root){ + if (is_fs2 == false) { + if (root) { File file = root.openNextFile(); while (file) { - if (file.isDirectory()) { - Serial.printf("[dir] /FS2/%s\n", file.name()); + Serial.printf("[dir] UserData%s/%s\n", path, file.name()); } else { - Serial.printf("[file] /FS2/%s (%d bytes)\n", file.name(), file.size()); + Serial.printf("[file] UserData%s/%s (%d bytes)\n", path, file.name(), file.size()); } - // move to next file file = root.openNextFile(); - } - root.close(); + root.close(); + } } - #endif + if (is_fs2 == true || strlen(path) == 0 || strcmp(path, "/") == 0) { + if (_store->getSecondaryFS() != nullptr) { + File root2 = _store->openRead(_store->getSecondaryFS(), path); + File file = root2.openNextFile(); + while (file) { + if (file.isDirectory()) { + Serial.printf("[dir] ExtraFS%s/%s\n", path, file.name()); + } else { + Serial.printf("[file] ExtraFS%s/%s (%d bytes)\n", path, file.name(), file.size()); + } + // move to next file + file = root2.openNextFile(); + } + root2.close(); + } + } } else if (memcmp(cli_command, "cat", 3) == 0) { // get path from command e.g: "cat /contacts3" const char *path = &cli_command[4]; - // bool is_fs2 = false; - if (memcmp(path, "FS1/", 4) == 0) { - path += 3; // skip "FS1" - } else if (memcmp(path, "FS2/", 4) == 0) { - path += 3; // skip "FS2" + if (memcmp(path, "UserData/", 9) == 0) { + path += 8; // skip "UserData" + } else if (memcmp(path, "ExtraFS/", 8) == 0) { + path += 7; // skip "ExtraFS" is_fs2 = true; + } else { + Serial.println("Invalid path provided, must start with UserData/ or ExtraFS/"); + cli_command[0] = 0; + return; } // log file content as hex @@ -1605,29 +1606,28 @@ void MyMesh::checkCLIRescueCmd() { } } else if (memcmp(cli_command, "rm ", 3) == 0) { - // get path from command e.g: "rm /adv_blobs" - const char *path = &cli_command[4]; + const char *path = &cli_command[3]; MESH_DEBUG_PRINTLN("Removing file: %s", path); // ensure path is not empty, or root dir if(!path || strlen(path) == 0 || strcmp(path, "/") == 0){ Serial.println("Invalid path provided"); } else { - bool is_fs2 = false; - if (memcmp(path, "FS1/", 4) == 0) { - path += 3; // skip "FS1" - } else if (memcmp(path, "FS2/", 4) == 0) { - path += 3; // skip "FS2" - is_fs2 = true; - } + bool is_fs2 = false; + if (memcmp(path, "UserData/", 9) == 0) { + path += 8; // skip "UserData" + } else if (memcmp(path, "ExtraFS/", 8) == 0) { + path += 7; // skip "ExtraFS" + is_fs2 = true; + } // remove file bool removed; if (is_fs2) { - MESH_DEBUG_PRINTLN("Removing file from FS2: %s", path); + MESH_DEBUG_PRINTLN("Removing file from ExtraFS: %s", path); removed = _store->removeFile(_store->getSecondaryFS(), path); } else { - MESH_DEBUG_PRINTLN("Removing file from FS1: %s", path); + MESH_DEBUG_PRINTLN("Removing file from UserData: %s", path); removed = _store->removeFile(path); } if(removed){