diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml index ccc7c4ca8..a6fb39b29 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -42,6 +42,7 @@ jobs: uses: ./.github/actions/setup-base - name: Trunk Check + if: ${{ github.event_name != 'workflow_dispatch' }} uses: trunk-io/trunk-action@v1 - name: Check ${{ matrix.board }} diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini index 5cc48e191..fb83ec2d4 100644 --- a/arch/esp32/esp32.ini +++ b/arch/esp32/esp32.ini @@ -35,7 +35,7 @@ lib_deps = https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2 h2zero/NimBLE-Arduino@^1.4.0 https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6 - caveman99/ESP32 Codec2@^1.0.1 + https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f lib_ignore = segger_rtt diff --git a/arch/esp32/esp32c3.ini b/arch/esp32/esp32c3.ini index cca95f48a..5ebb789ad 100644 --- a/arch/esp32/esp32c3.ini +++ b/arch/esp32/esp32c3.ini @@ -34,8 +34,7 @@ lib_deps = https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2 h2zero/NimBLE-Arduino@^1.4.0 https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6 - caveman99/ESP32 Codec2@^1.0.1 - + https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f lib_ignore = segger_rtt ESP32 BLE Arduino diff --git a/arch/esp32/esp32s2.ini b/arch/esp32/esp32s2.ini index b266d1792..6e75c08c9 100644 --- a/arch/esp32/esp32s2.ini +++ b/arch/esp32/esp32s2.ini @@ -35,7 +35,7 @@ lib_deps = ${environmental_base.lib_deps} https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2 https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6 - caveman99/ESP32 Codec2@^1.0.1 + https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f lib_ignore = segger_rtt diff --git a/arch/esp32/esp32s3.ini b/arch/esp32/esp32s3.ini index 9a042b22b..bb0214f46 100644 --- a/arch/esp32/esp32s3.ini +++ b/arch/esp32/esp32s3.ini @@ -35,7 +35,7 @@ lib_deps = https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2 h2zero/NimBLE-Arduino@^1.4.0 https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6 - caveman99/ESP32 Codec2@^1.0.1 + https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f lib_ignore = segger_rtt diff --git a/bin/generate_ci_matrix.py b/bin/generate_ci_matrix.py new file mode 100755 index 000000000..2501e83c1 --- /dev/null +++ b/bin/generate_ci_matrix.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python + +"""Generate the CI matrix""" + +import configparser +import json +import os +import sys + +rootdir = "variants/" + +options = sys.argv[1:] + +outlist = [] + +if len(options) < 1: + print(json.dumps(outlist)) + exit() + +for subdir, dirs, files in os.walk(rootdir): + for file in files: + if file == "platformio.ini": + config = configparser.ConfigParser() + config.read(subdir + "/" + file) + for c in config.sections(): + if c.startswith("env:"): + section = config[c].name[4:] + if "extends" in config[config[c].name]: + if config[config[c].name]["extends"] == options[0] + "_base": + if "board_level" in config[config[c].name]: + if ( + config[config[c].name]["board_level"] == "extra" + ) & ("extra" in options): + outlist.append(section) + else: + outlist.append(section) + +print(json.dumps(outlist)) diff --git a/bin/regen-protos.bat b/bin/regen-protos.bat index aa2a2684f..1422f7914 100644 --- a/bin/regen-protos.bat +++ b/bin/regen-protos.bat @@ -1,5 +1 @@ -cd protobufs && ..\nanopb-0.4.7\generator-bin\protoc.exe --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs ..\protobufs\meshtastic\*.proto - -@REM cd ../src/mesh/generated/meshtastic -@REM sed -i 's/#include "meshtastic/#include "./g' * -@REM sed -i 's/meshtastic_//g' * +cd protobufs && ..\nanopb-0.4.7\generator-bin\protoc.exe --experimental_allow_proto3_optional --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs ..\protobufs\meshtastic\*.proto diff --git a/platformio.ini b/platformio.ini index d8c55fb78..508f3615b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -85,7 +85,7 @@ lib_deps = ${env.lib_deps} mprograms/QMC5883LCompass@^1.1.1 end2endzone/NonBlockingRTTTL@^1.3.0 - https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#52b5282639d08a8cbd4b748363089eed6102dc76 + https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#5cf62b36c6f30bc72a07bdb2c11fc9a22d1e31da build_flags = ${env.build_flags} -Os -DRADIOLIB_SPI_PARANOID=0 build_src_filter = ${env.build_src_filter} - @@ -105,7 +105,7 @@ lib_deps = adafruit/Adafruit Unified Sensor@^1.1.9 adafruit/Adafruit BMP280 Library@^2.6.6 adafruit/Adafruit BME280 Library@^2.2.2 - adafruit/Adafruit BME680 Library@^2.0.1 + https://github.com/meshtastic/BSEC-Arduino-library.git#452f9a7ffa8b53e1debe2c454fe375dfad98b507 adafruit/Adafruit MCP9808 Library@^2.0.0 adafruit/Adafruit INA260 Library@^1.5.0 adafruit/Adafruit INA219@^1.2.0 diff --git a/protobufs b/protobufs index 641d7c3a4..ef2bc66bb 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 641d7c3a460de9cc580bc2b8a0812e8b9d417b05 +Subproject commit ef2bc66bba41e8ef98ea893e46eb36a2da40cb5e diff --git a/src/ButtonThread.h b/src/ButtonThread.h index f35c53a46..0a8b2afa5 100644 --- a/src/ButtonThread.h +++ b/src/ButtonThread.h @@ -45,10 +45,10 @@ class ButtonThread : public concurrency::OSThread ButtonThread() : OSThread("Button") { #ifdef BUTTON_PIN - userButton = OneButton(BUTTON_PIN, true, true); + userButton = OneButton(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, true, true); #ifdef INPUT_PULLUP_SENSE // Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did - pinMode(BUTTON_PIN, INPUT_PULLUP_SENSE); + pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT_PULLUP_SENSE); #endif userButton.attachClick(userButtonPressed); userButton.setClickTicks(300); @@ -57,7 +57,7 @@ class ButtonThread : public concurrency::OSThread userButton.attachMultiClick(userButtonMultiPressed); userButton.attachLongPressStart(userButtonPressedLongStart); userButton.attachLongPressStop(userButtonPressedLongStop); - wakeOnIrq(BUTTON_PIN, FALLING); + wakeOnIrq(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, FALLING); #endif #ifdef BUTTON_PIN_ALT userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true); @@ -115,7 +115,9 @@ class ButtonThread : public concurrency::OSThread { // LOG_DEBUG("press!\n"); #ifdef BUTTON_PIN - if ((BUTTON_PIN != moduleConfig.canned_message.inputbroker_pin_press) || !moduleConfig.canned_message.enabled) { + if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) != + moduleConfig.canned_message.inputbroker_pin_press) || + !moduleConfig.canned_message.enabled) { powerFSM.trigger(EVENT_PRESS); } #endif @@ -124,13 +126,8 @@ class ButtonThread : public concurrency::OSThread { // LOG_DEBUG("Long press!\n"); // If user button is held down for 5 seconds, shutdown the device. - if ((millis() - longPressTime > 5 * 1000) && (longPressTime > 0)) { -#ifdef HAS_PMU - if (pmu_found == true) { - setLed(false); - power->shutdown(); - } -#elif defined(ARCH_NRF52) || defined(ARCH_ESP32) + if ((millis() - longPressTime > 5000) && (longPressTime > 0)) { +#if defined(ARCH_NRF52) || defined(ARCH_ESP32) // Do actual shutdown when button released, otherwise the button release // may wake the board immediatedly. if ((!shutdown_on_long_stop) && (millis() > 30 * 1000)) { diff --git a/src/FSCommon.cpp b/src/FSCommon.cpp index 32e5d7e28..cc99caed8 100644 --- a/src/FSCommon.cpp +++ b/src/FSCommon.cpp @@ -34,6 +34,7 @@ bool copyFile(const char *from, const char *to) f2.write(cbuffer, i); } + f2.flush(); f2.close(); f1.close(); return true; diff --git a/src/Power.cpp b/src/Power.cpp index 6c4851c11..6bd679ae2 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -212,7 +212,7 @@ Power::Power() : OSThread("Power") statusHandler = {}; low_voltage_counter = 0; #ifdef DEBUG_HEAP - lastheap = ESP.getFreeHeap(); + lastheap = memGet.getFreeHeap(); #endif } @@ -277,12 +277,11 @@ void Power::shutdown() LOG_INFO("Shutting down\n"); #ifdef HAS_PMU - if (PMU) { + if (pmu_found == true) { PMU->setChargingLedMode(XPOWERS_CHG_LED_OFF); + PMU->shutdown(); } -#endif - -#if defined(ARCH_NRF52) || defined(ARCH_ESP32) +#elif defined(ARCH_NRF52) || defined(ARCH_ESP32) #ifdef PIN_LED1 ledOff(PIN_LED1); #endif @@ -328,7 +327,7 @@ void Power::readPowerStatus() powerStatus2.getIsCharging(), powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent()); newStatus.notifyObservers(&powerStatus2); #ifdef DEBUG_HEAP - if (lastheap != ESP.getFreeHeap()) { + if (lastheap != memGet.getFreeHeap()) { LOG_DEBUG("Threads running:"); int running = 0; for (int i = 0; i < MAX_THREADS; i++) { @@ -339,9 +338,9 @@ void Power::readPowerStatus() } } LOG_DEBUG("\n"); - LOG_DEBUG("Heap status: %d/%d bytes free (%d), running %d/%d threads\n", ESP.getFreeHeap(), ESP.getHeapSize(), - ESP.getFreeHeap() - lastheap, running, concurrency::mainController.size(false)); - lastheap = ESP.getFreeHeap(); + LOG_DEBUG("Heap status: %d/%d bytes free (%d), running %d/%d threads\n", memGet.getFreeHeap(), memGet.getHeapSize(), + memGet.getFreeHeap() - lastheap, running, concurrency::mainController.size(false)); + lastheap = memGet.getFreeHeap(); } #ifdef DEBUG_HEAP_MQTT if (mqtt) { @@ -350,15 +349,17 @@ void Power::readPowerStatus() getMacAddr(dmac); // Get our hardware ID char mac[18]; sprintf(mac, "!%02x%02x%02x%02x", dmac[2], dmac[3], dmac[4], dmac[5]); - auto newHeap = ESP.getFreeHeap(); - std::string heapTopic = "msh/2/heap/" + std::string(mac); + + auto newHeap = memGet.getFreeHeap(); + std::string heapTopic = + (*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh") + std::string("/2/heap/") + std::string(mac); std::string heapString = std::to_string(newHeap); mqtt->pubSub.publish(heapTopic.c_str(), heapString.c_str(), false); - // auto fragHeap = ESP.getHeapFragmentation(); auto wifiRSSI = WiFi.RSSI(); - heapTopic = "msh/2/wifi/" + std::string(mac); + std::string wifiTopic = + (*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh") + std::string("/2/wifi/") + std::string(mac); std::string wifiString = std::to_string(wifiRSSI); - mqtt->pubSub.publish(heapTopic.c_str(), wifiString.c_str(), false); + mqtt->pubSub.publish(wifiTopic.c_str(), wifiString.c_str(), false); } #endif diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 2139d9d8f..7babc2067 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -93,18 +93,23 @@ static void lsIdle() powerFSM.trigger(EVENT_SERIAL_CONNECTED); break; - case ESP_SLEEP_WAKEUP_GPIO: - // GPIO of BUTTON_PIN (if available) triggered the wakeup - powerFSM.trigger(EVENT_PRESS); - break; - default: - // We woke for some other reason (device interrupt) + // We woke for some other reason (button press, device interrupt) // uint64_t status = esp_sleep_get_ext1_wakeup_status(); LOG_INFO("wakeCause2 %d\n", wakeCause2); - // Let the NB state handle the IRQ (and that state will handle stuff like IRQs etc) - // we lie and say "wake timer" because the interrupt will be handled by the regular IRQ code - powerFSM.trigger(EVENT_WAKE_TIMER); + +#ifdef BUTTON_PIN + bool pressed = !digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN); +#else + bool pressed = false; +#endif + if (pressed) { // If we woke because of press, instead generate a PRESS event. + powerFSM.trigger(EVENT_PRESS); + } else { + // Otherwise let the NB state handle the IRQ (and that state will handle stuff like IRQs etc) + // we lie and say "wake timer" because the interrupt will be handled by the regular IRQ code + powerFSM.trigger(EVENT_WAKE_TIMER); + } break; } } else { @@ -348,4 +353,4 @@ void PowerFSM_setup() #endif powerFSM.run_machine(); // run one interation of the state machine, so we run our on enter tasks for the initial DARK state -} +} \ No newline at end of file diff --git a/src/concurrency/OSThread.cpp b/src/concurrency/OSThread.cpp index af50d28f5..c71d3510e 100644 --- a/src/concurrency/OSThread.cpp +++ b/src/concurrency/OSThread.cpp @@ -1,5 +1,6 @@ #include "OSThread.h" #include "configuration.h" +#include "memGet.h" #include namespace concurrency @@ -75,12 +76,12 @@ bool OSThread::shouldRun(unsigned long time) void OSThread::run() { #ifdef DEBUG_HEAP - auto heap = ESP.getFreeHeap(); + auto heap = memGet.getFreeHeap(); #endif currentThread = this; auto newDelay = runOnce(); #ifdef DEBUG_HEAP - auto newHeap = ESP.getFreeHeap(); + auto newHeap = memGet.getFreeHeap(); if (newHeap < heap) LOG_DEBUG("------ Thread %s leaked heap %d -> %d (%d) ------\n", ThreadName.c_str(), heap, newHeap, newHeap - heap); if (heap < newHeap) diff --git a/src/main.cpp b/src/main.cpp index bd35bdaec..7af41116c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -142,17 +142,6 @@ static int32_t ledBlinker() setLed(ledOn); -#ifdef ARCH_ESP32 - auto newHeap = ESP.getFreeHeap(); - if (newHeap < 11000) { - LOG_DEBUG("\n\n====== heap too low [11000] -> reboot in 1s ======\n\n"); -#ifdef HAS_SCREEN - screen->startRebootScreen(); -#endif - rebootAtMsec = millis() + 900; - } -#endif - // have a very sparse duty cycle of LED being on, unless charging, then blink 0.5Hz square wave rate to indicate that return powerStatus->getIsCharging() ? 1000 : (ledOn ? 1 : 1000); } @@ -229,10 +218,10 @@ void setup() // If the button is connected to GPIO 12, don't enable the ability to use // meshtasticAdmin on the device. - pinMode(BUTTON_PIN, INPUT); + pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT); #ifdef BUTTON_NEED_PULLUP - gpio_pullup_en((gpio_num_t)BUTTON_PIN); + gpio_pullup_en((gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN)); delay(10); #endif @@ -400,10 +389,7 @@ void setup() // scanEInkDevice(); #endif -#if HAS_BUTTON - // Buttons & LED - buttonThread = new ButtonThread(); -#endif + // LED init #ifdef LED_PIN pinMode(LED_PIN, OUTPUT); @@ -428,6 +414,11 @@ void setup() if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) router = new FloodingRouter(); +#if HAS_BUTTON + // Buttons. Moved here cause we need NodeDB to be initialized + buttonThread = new ButtonThread(); +#endif + playStartMelody(); // fixed screen override? diff --git a/src/main.h b/src/main.h index db5fc26d8..645ba2ee2 100644 --- a/src/main.h +++ b/src/main.h @@ -5,6 +5,7 @@ #include "PowerStatus.h" #include "detect/ScanI2C.h" #include "graphics/Screen.h" +#include "memGet.h" #include "mesh/generated/meshtastic/config.pb.h" #include "mesh/generated/meshtastic/telemetry.pb.h" #include diff --git a/src/memGet.cpp b/src/memGet.cpp new file mode 100644 index 000000000..9f59d29ff --- /dev/null +++ b/src/memGet.cpp @@ -0,0 +1,46 @@ +#include "memGet.h" +#include "configuration.h" + +MemGet memGet; + +uint32_t MemGet::getFreeHeap() +{ +#ifdef ARCH_ESP32 + return ESP.getFreeHeap(); +#elif defined(ARCH_NRF52) + return dbgHeapFree(); +#else + // this platform does not have heap management function implemented + return UINT32_MAX; +#endif +} + +uint32_t MemGet::getHeapSize() +{ +#ifdef ARCH_ESP32 + return ESP.getHeapSize(); +#elif defined(ARCH_NRF52) + return dbgHeapTotal(); +#else + // this platform does not have heap management function implemented + return UINT32_MAX; +#endif +} + +uint32_t MemGet::getFreePsram() +{ +#ifdef ARCH_ESP32 + return ESP.getFreePsram(); +#else + return 0; +#endif +} + +uint32_t MemGet::getPsramSize() +{ +#ifdef ARCH_ESP32 + return ESP.getPsramSize(); +#else + return 0; +#endif +} diff --git a/src/memGet.h b/src/memGet.h new file mode 100644 index 000000000..130d2ca7e --- /dev/null +++ b/src/memGet.h @@ -0,0 +1,18 @@ +#pragma once +#ifndef _MT_MEMGET_H +#define _MT_MEMGET_H + +#include + +class MemGet +{ + public: + uint32_t getFreeHeap(); + uint32_t getHeapSize(); + uint32_t getFreePsram(); + uint32_t getPsramSize(); +}; + +extern MemGet memGet; + +#endif diff --git a/src/mesh/CryptoEngine.cpp b/src/mesh/CryptoEngine.cpp index 9b5810650..1e44cb9b7 100644 --- a/src/mesh/CryptoEngine.cpp +++ b/src/mesh/CryptoEngine.cpp @@ -1,6 +1,8 @@ #include "CryptoEngine.h" #include "configuration.h" +concurrency::Lock *cryptLock; + void CryptoEngine::setKey(const CryptoKey &k) { LOG_DEBUG("Using AES%d key!\n", k.length * 8); diff --git a/src/mesh/CryptoEngine.h b/src/mesh/CryptoEngine.h index 1dda7ce31..2737dab2d 100644 --- a/src/mesh/CryptoEngine.h +++ b/src/mesh/CryptoEngine.h @@ -1,7 +1,10 @@ #pragma once +#include "concurrency/LockGuard.h" #include +extern concurrency::Lock *cryptLock; + struct CryptoKey { uint8_t bytes[32]; diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index c7a42cb09..5ee839b80 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -490,6 +490,7 @@ bool NodeDB::saveProto(const char *filename, size_t protoSize, const pb_msgdesc_ } else { okay = true; } + f.flush(); f.close(); // brief window of risk here ;-) @@ -689,11 +690,11 @@ void NodeDB::updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxS /** Update user info for this node based on received user data */ -void NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p) +bool NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p) { meshtastic_NodeInfo *info = getOrCreateNode(nodeId); if (!info) { - return; + return false; } LOG_DEBUG("old user %s/%s/%s\n", info->user.id, info->user.long_name, info->user.short_name); @@ -713,6 +714,8 @@ void NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p) // We just changed something important about the user, store our DB saveToDisk(SEGMENT_DEVICESTATE); } + + return changed; } /// given a subpacket sniffed from the network, update our DB state @@ -765,7 +768,7 @@ meshtastic_NodeInfo *NodeDB::getOrCreateNode(NodeNum n) meshtastic_NodeInfo *info = getNode(n); if (!info) { - if (*numNodes >= MAX_NUM_NODES) { + if ((*numNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfo_size * 3)) { screen->print("warning: node_db full! erasing oldest entry\n"); // look for oldest node and erase it uint32_t oldest = UINT32_MAX; diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index 2822ffbf6..541b51f83 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -86,7 +86,7 @@ class NodeDB /** Update user info for this node based on received user data */ - void updateUser(uint32_t nodeId, const meshtastic_User &p); + bool updateUser(uint32_t nodeId, const meshtastic_User &p); /// @return our node number NodeNum getNodeNum() { return myNodeInfo.my_node_num; } diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index b3aee4e7d..e85d85450 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -55,6 +55,10 @@ Router::Router() : concurrency::OSThread("Router"), fromRadioQueue(MAX_RX_FROMRA LOG_DEBUG("Size of MeshPacket %d\n", sizeof(MeshPacket)); */ fromRadioQueue.setReader(this); + + // init Lockguard for crypt operations + assert(!cryptLock); + cryptLock = new concurrency::Lock(); } /** @@ -305,6 +309,8 @@ void Router::sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Rout bool perhapsDecode(meshtastic_MeshPacket *p) { + concurrency::LockGuard g(cryptLock); + if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER && config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_ALL_SKIP_DECODING) return false; @@ -371,6 +377,8 @@ bool perhapsDecode(meshtastic_MeshPacket *p) */ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p) { + concurrency::LockGuard g(cryptLock); + // If the packet is not yet encrypted, do so now if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) { size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_Data_msg, &p->decoded); diff --git a/src/mesh/generated/meshtastic/channel.pb.h b/src/mesh/generated/meshtastic/channel.pb.h index 83ef7b5fc..535962ae6 100644 --- a/src/mesh/generated/meshtastic/channel.pb.h +++ b/src/mesh/generated/meshtastic/channel.pb.h @@ -31,11 +31,9 @@ typedef enum _meshtastic_Channel_Role { /* Struct definitions */ typedef PB_BYTES_ARRAY_T(32) meshtastic_ChannelSettings_psk_t; -/* Full settings (center freq, spread factor, pre-shared secret key etc...) - needed to configure a radio for speaking on a particular channel This - information can be encoded as a QRcode/url so that other users can configure +/* This information can be encoded as a QRcode/url so that other users can configure their radio to join the same channel. - A note about how channel names are shown to users: channelname-Xy + A note about how channel names are shown to users: channelname-X poundsymbol is a prefix used to indicate this is a channel name (idea from @professr). Where X is a letter from A-Z (base 26) representing a hash of the PSK for this channel - so that if the user changes anything about the channel (which does @@ -45,8 +43,6 @@ typedef PB_BYTES_ARRAY_T(32) meshtastic_ChannelSettings_psk_t; The PSK is hashed into this letter by "0x41 + [xor all bytes of the psk ] modulo 26" This also allows the option of someday if people have the PSK off (zero), the users COULD type in a channel name and be able to talk. - Y is a lower case letter from a-z that represents the channel 'speed' settings - (for some future definition of speed) FIXME: Add description of multi-channel support and how primary vs secondary channels are used. FIXME: explain how apps use channels for security. explain how remote settings and remote gpio are managed as an example */ @@ -60,7 +56,7 @@ typedef struct _meshtastic_ChannelSettings { because they are listed in this source code. Those bytes are mapped using the following scheme: `0` = No crypto - `1` = The special "default" channel key: {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59, 0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0xbf} + `1` = The special "default" channel key: {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59, 0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0x01} `2` through 10 = The default channel key, except with 1 through 9 added to the last byte. Shown to user as simple1 through 10 */ meshtastic_ChannelSettings_psk_t psk; diff --git a/src/mesh/generated/meshtastic/clientonly.pb.c b/src/mesh/generated/meshtastic/clientonly.pb.c new file mode 100644 index 000000000..ebc2ffabc --- /dev/null +++ b/src/mesh/generated/meshtastic/clientonly.pb.c @@ -0,0 +1,12 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.7 */ + +#include "meshtastic/clientonly.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(meshtastic_DeviceProfile, meshtastic_DeviceProfile, 2) + + + diff --git a/src/mesh/generated/meshtastic/clientonly.pb.h b/src/mesh/generated/meshtastic/clientonly.pb.h new file mode 100644 index 000000000..0f70e09c6 --- /dev/null +++ b/src/mesh/generated/meshtastic/clientonly.pb.h @@ -0,0 +1,73 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.7 */ + +#ifndef PB_MESHTASTIC_MESHTASTIC_CLIENTONLY_PB_H_INCLUDED +#define PB_MESHTASTIC_MESHTASTIC_CLIENTONLY_PB_H_INCLUDED +#include +#include "meshtastic/localonly.pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +/* This abstraction is used to contain any configuration for provisioning a node on any client. + It is useful for importing and exporting configurations. */ +typedef struct _meshtastic_DeviceProfile { + /* Long name for the node */ + bool has_long_name; + char long_name[40]; + /* Short name of the node */ + bool has_short_name; + char short_name[5]; + /* The url of the channels from our node */ + pb_callback_t channel_url; + /* The Config of the node */ + bool has_config; + meshtastic_LocalConfig config; + /* The ModuleConfig of the node */ + bool has_module_config; + meshtastic_LocalModuleConfig module_config; +} meshtastic_DeviceProfile; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define meshtastic_DeviceProfile_init_default {false, "", false, "", {{NULL}, NULL}, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default} +#define meshtastic_DeviceProfile_init_zero {false, "", false, "", {{NULL}, NULL}, false, meshtastic_LocalConfig_init_zero, false, meshtastic_LocalModuleConfig_init_zero} + +/* Field tags (for use in manual encoding/decoding) */ +#define meshtastic_DeviceProfile_long_name_tag 1 +#define meshtastic_DeviceProfile_short_name_tag 2 +#define meshtastic_DeviceProfile_channel_url_tag 3 +#define meshtastic_DeviceProfile_config_tag 4 +#define meshtastic_DeviceProfile_module_config_tag 5 + +/* Struct field encoding specification for nanopb */ +#define meshtastic_DeviceProfile_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, STRING, long_name, 1) \ +X(a, STATIC, OPTIONAL, STRING, short_name, 2) \ +X(a, CALLBACK, OPTIONAL, STRING, channel_url, 3) \ +X(a, STATIC, OPTIONAL, MESSAGE, config, 4) \ +X(a, STATIC, OPTIONAL, MESSAGE, module_config, 5) +#define meshtastic_DeviceProfile_CALLBACK pb_default_field_callback +#define meshtastic_DeviceProfile_DEFAULT NULL +#define meshtastic_DeviceProfile_config_MSGTYPE meshtastic_LocalConfig +#define meshtastic_DeviceProfile_module_config_MSGTYPE meshtastic_LocalModuleConfig + +extern const pb_msgdesc_t meshtastic_DeviceProfile_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define meshtastic_DeviceProfile_fields &meshtastic_DeviceProfile_msg + +/* Maximum encoded size of messages (where known) */ +/* meshtastic_DeviceProfile_size depends on runtime parameters */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index 6788bd426..56beee95e 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -188,7 +188,7 @@ extern const pb_msgdesc_t meshtastic_OEMStore_msg; /* Maximum encoded size of messages (where known) */ #define meshtastic_ChannelFile_size 638 #define meshtastic_DeviceState_size 22040 -#define meshtastic_OEMStore_size 3024 +#define meshtastic_OEMStore_size 3041 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index 23865f47d..0cfcb2491 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -157,7 +157,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; /* Maximum encoded size of messages (where known) */ #define meshtastic_LocalConfig_size 456 -#define meshtastic_LocalModuleConfig_size 422 +#define meshtastic_LocalModuleConfig_size 439 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/mesh.pb.c b/src/mesh/generated/meshtastic/mesh.pb.c index 0c3c155f6..ce7d48b14 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.c +++ b/src/mesh/generated/meshtastic/mesh.pb.c @@ -48,6 +48,12 @@ PB_BIND(meshtastic_ToRadio, meshtastic_ToRadio, 2) PB_BIND(meshtastic_Compressed, meshtastic_Compressed, AUTO) +PB_BIND(meshtastic_NeighborInfo, meshtastic_NeighborInfo, AUTO) + + +PB_BIND(meshtastic_Neighbor, meshtastic_Neighbor, AUTO) + + PB_BIND(meshtastic_DeviceMetadata, meshtastic_DeviceMetadata, AUTO) diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index e95cffdfe..984939702 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -680,6 +680,25 @@ typedef struct _meshtastic_Compressed { meshtastic_Compressed_data_t data; } meshtastic_Compressed; +/* A single edge in the mesh */ +typedef struct _meshtastic_Neighbor { + /* Node ID of neighbor */ + uint32_t node_id; + /* SNR of last heard message */ + float snr; +} meshtastic_Neighbor; + +/* Full info on edges for a single node */ +typedef struct _meshtastic_NeighborInfo { + /* The node ID of the node sending info on its neighbors */ + uint32_t node_id; + /* Field to pass neighbor info for the next sending cycle */ + uint32_t last_sent_by_id; + /* The list of out edges from this node */ + pb_size_t neighbors_count; + meshtastic_Neighbor neighbors[10]; +} meshtastic_NeighborInfo; + /* Device metadata response */ typedef struct _meshtastic_DeviceMetadata { /* Device firmware version string */ @@ -813,6 +832,8 @@ extern "C" { #define meshtastic_Compressed_portnum_ENUMTYPE meshtastic_PortNum + + #define meshtastic_DeviceMetadata_role_ENUMTYPE meshtastic_Config_DeviceConfig_Role #define meshtastic_DeviceMetadata_hw_model_ENUMTYPE meshtastic_HardwareModel @@ -832,6 +853,8 @@ extern "C" { #define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}} #define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}} #define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}} +#define meshtastic_NeighborInfo_init_default {0, 0, 0, {meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default}} +#define meshtastic_Neighbor_init_default {0, 0} #define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN} #define meshtastic_Position_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0} @@ -847,6 +870,8 @@ extern "C" { #define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}} #define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}} #define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}} +#define meshtastic_NeighborInfo_init_zero {0, 0, 0, {meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero}} +#define meshtastic_Neighbor_init_zero {0, 0} #define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN} /* Field tags (for use in manual encoding/decoding) */ @@ -948,6 +973,11 @@ extern "C" { #define meshtastic_ToRadio_xmodemPacket_tag 5 #define meshtastic_Compressed_portnum_tag 1 #define meshtastic_Compressed_data_tag 2 +#define meshtastic_Neighbor_node_id_tag 1 +#define meshtastic_Neighbor_snr_tag 2 +#define meshtastic_NeighborInfo_node_id_tag 1 +#define meshtastic_NeighborInfo_last_sent_by_id_tag 2 +#define meshtastic_NeighborInfo_neighbors_tag 3 #define meshtastic_DeviceMetadata_firmware_version_tag 1 #define meshtastic_DeviceMetadata_device_state_version_tag 2 #define meshtastic_DeviceMetadata_canShutdown_tag 3 @@ -1157,6 +1187,20 @@ X(a, STATIC, SINGULAR, BYTES, data, 2) #define meshtastic_Compressed_CALLBACK NULL #define meshtastic_Compressed_DEFAULT NULL +#define meshtastic_NeighborInfo_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, node_id, 1) \ +X(a, STATIC, SINGULAR, UINT32, last_sent_by_id, 2) \ +X(a, STATIC, REPEATED, MESSAGE, neighbors, 3) +#define meshtastic_NeighborInfo_CALLBACK NULL +#define meshtastic_NeighborInfo_DEFAULT NULL +#define meshtastic_NeighborInfo_neighbors_MSGTYPE meshtastic_Neighbor + +#define meshtastic_Neighbor_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, node_id, 1) \ +X(a, STATIC, SINGULAR, FLOAT, snr, 2) +#define meshtastic_Neighbor_CALLBACK NULL +#define meshtastic_Neighbor_DEFAULT NULL + #define meshtastic_DeviceMetadata_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, firmware_version, 1) \ X(a, STATIC, SINGULAR, UINT32, device_state_version, 2) \ @@ -1184,6 +1228,8 @@ extern const pb_msgdesc_t meshtastic_QueueStatus_msg; extern const pb_msgdesc_t meshtastic_FromRadio_msg; extern const pb_msgdesc_t meshtastic_ToRadio_msg; extern const pb_msgdesc_t meshtastic_Compressed_msg; +extern const pb_msgdesc_t meshtastic_NeighborInfo_msg; +extern const pb_msgdesc_t meshtastic_Neighbor_msg; extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ @@ -1201,6 +1247,8 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg; #define meshtastic_FromRadio_fields &meshtastic_FromRadio_msg #define meshtastic_ToRadio_fields &meshtastic_ToRadio_msg #define meshtastic_Compressed_fields &meshtastic_Compressed_msg +#define meshtastic_NeighborInfo_fields &meshtastic_NeighborInfo_msg +#define meshtastic_Neighbor_fields &meshtastic_Neighbor_msg #define meshtastic_DeviceMetadata_fields &meshtastic_DeviceMetadata_msg /* Maximum encoded size of messages (where known) */ @@ -1211,6 +1259,8 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg; #define meshtastic_LogRecord_size 81 #define meshtastic_MeshPacket_size 321 #define meshtastic_MyNodeInfo_size 179 +#define meshtastic_NeighborInfo_size 142 +#define meshtastic_Neighbor_size 11 #define meshtastic_NodeInfo_size 261 #define meshtastic_Position_size 137 #define meshtastic_QueueStatus_size 23 diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h index f94114e15..e59d33dd0 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.h +++ b/src/mesh/generated/meshtastic/module_config.pb.h @@ -98,6 +98,9 @@ typedef struct _meshtastic_ModuleConfig_MQTTConfig { bool json_enabled; /* If true, we attempt to establish a secure connection using TLS */ bool tls_enabled; + /* The root topic to use for MQTT messages. Default is "msh". + This is useful if you want to use a single MQTT server for multiple meshtastic networks and separate them via ACLs */ + char root[16]; } meshtastic_ModuleConfig_MQTTConfig; /* RemoteHardwareModule Config */ @@ -325,7 +328,7 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_ModuleConfig_init_default {0, {meshtastic_ModuleConfig_MQTTConfig_init_default}} -#define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0} +#define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0, ""} #define meshtastic_ModuleConfig_RemoteHardwareConfig_init_default {0} #define meshtastic_ModuleConfig_AudioConfig_init_default {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0} #define meshtastic_ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN} @@ -335,7 +338,7 @@ extern "C" { #define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} #define meshtastic_ModuleConfig_init_zero {0, {meshtastic_ModuleConfig_MQTTConfig_init_zero}} -#define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0} +#define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0, ""} #define meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero {0} #define meshtastic_ModuleConfig_AudioConfig_init_zero {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0} #define meshtastic_ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN} @@ -353,6 +356,7 @@ extern "C" { #define meshtastic_ModuleConfig_MQTTConfig_encryption_enabled_tag 5 #define meshtastic_ModuleConfig_MQTTConfig_json_enabled_tag 6 #define meshtastic_ModuleConfig_MQTTConfig_tls_enabled_tag 7 +#define meshtastic_ModuleConfig_MQTTConfig_root_tag 8 #define meshtastic_ModuleConfig_RemoteHardwareConfig_enabled_tag 1 #define meshtastic_ModuleConfig_AudioConfig_codec2_enabled_tag 1 #define meshtastic_ModuleConfig_AudioConfig_ptt_pin_tag 2 @@ -448,7 +452,8 @@ X(a, STATIC, SINGULAR, STRING, username, 3) \ X(a, STATIC, SINGULAR, STRING, password, 4) \ X(a, STATIC, SINGULAR, BOOL, encryption_enabled, 5) \ X(a, STATIC, SINGULAR, BOOL, json_enabled, 6) \ -X(a, STATIC, SINGULAR, BOOL, tls_enabled, 7) +X(a, STATIC, SINGULAR, BOOL, tls_enabled, 7) \ +X(a, STATIC, SINGULAR, STRING, root, 8) #define meshtastic_ModuleConfig_MQTTConfig_CALLBACK NULL #define meshtastic_ModuleConfig_MQTTConfig_DEFAULT NULL @@ -566,13 +571,13 @@ extern const pb_msgdesc_t meshtastic_ModuleConfig_CannedMessageConfig_msg; #define meshtastic_ModuleConfig_AudioConfig_size 19 #define meshtastic_ModuleConfig_CannedMessageConfig_size 49 #define meshtastic_ModuleConfig_ExternalNotificationConfig_size 40 -#define meshtastic_ModuleConfig_MQTTConfig_size 203 +#define meshtastic_ModuleConfig_MQTTConfig_size 220 #define meshtastic_ModuleConfig_RangeTestConfig_size 10 #define meshtastic_ModuleConfig_RemoteHardwareConfig_size 2 #define meshtastic_ModuleConfig_SerialConfig_size 26 #define meshtastic_ModuleConfig_StoreForwardConfig_size 22 #define meshtastic_ModuleConfig_TelemetryConfig_size 26 -#define meshtastic_ModuleConfig_size 206 +#define meshtastic_ModuleConfig_size 223 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/portnums.pb.h b/src/mesh/generated/meshtastic/portnums.pb.h index 59cf0ebe5..ccf94372e 100644 --- a/src/mesh/generated/meshtastic/portnums.pb.h +++ b/src/mesh/generated/meshtastic/portnums.pb.h @@ -85,6 +85,8 @@ typedef enum _meshtastic_PortNum { /* Provides a traceroute functionality to show the route a packet towards a certain destination would take on the mesh. */ meshtastic_PortNum_TRACEROUTE_APP = 70, + /* Aggregates edge info for the network by sending out a list of each node's neighbors */ + meshtastic_PortNum_NEIGHBORINFO_APP = 71, /* Private applications should use portnums >= 256. To simplify initial development and testing you can use "PRIVATE_APP" in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/firmware/blob/master/bin/regen-protos.sh)) */ diff --git a/src/mesh/http/ContentHandler.cpp b/src/mesh/http/ContentHandler.cpp index 03aab54ae..9ddb5ca3a 100644 --- a/src/mesh/http/ContentHandler.cpp +++ b/src/mesh/http/ContentHandler.cpp @@ -234,15 +234,18 @@ void htmlDeleteDir(const char *dirname) while (file) { if (file.isDirectory() && !String(file.name()).endsWith(".")) { htmlDeleteDir(file.name()); + file.flush(); file.close(); } else { String fileName = String(file.name()); + file.flush(); file.close(); LOG_DEBUG(" %s\n", fileName.c_str()); FSCom.remove(fileName); } file = root.openNextFile(); } + root.flush(); root.close(); } @@ -521,7 +524,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res) std::string pathname = "/static/" + filename; // Create a new file to stream the data into - File file = FSCom.open(pathname.c_str(), "w"); + File file = FSCom.open(pathname.c_str(), FILE_O_WRITE); size_t fileLength = 0; didwrite = true; @@ -536,6 +539,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res) // Abort the transfer if there is less than 50k space left on the filesystem. if (FSCom.totalBytes() - FSCom.usedBytes() < 51200) { + file.flush(); file.close(); res->println("

Write aborted! Reserving 50k on filesystem.

"); @@ -553,6 +557,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res) } // enableLoopWDT(); + file.flush(); file.close(); res->printf("

Saved %d bytes to %s

", (int)fileLength, pathname.c_str()); } @@ -622,10 +627,10 @@ void handleReport(HTTPRequest *req, HTTPResponse *res) // data->memory JSONObject jsonObjMemory; - jsonObjMemory["heap_total"] = new JSONValue((int)ESP.getHeapSize()); - jsonObjMemory["heap_free"] = new JSONValue((int)ESP.getFreeHeap()); - jsonObjMemory["psram_total"] = new JSONValue((int)ESP.getPsramSize()); - jsonObjMemory["psram_free"] = new JSONValue((int)ESP.getFreePsram()); + jsonObjMemory["heap_total"] = new JSONValue((int)memGet.getHeapSize()); + jsonObjMemory["heap_free"] = new JSONValue((int)memGet.getFreeHeap()); + jsonObjMemory["psram_total"] = new JSONValue((int)memGet.getPsramSize()); + jsonObjMemory["psram_free"] = new JSONValue((int)memGet.getFreePsram()); jsonObjMemory["fs_total"] = new JSONValue((int)FSCom.totalBytes()); jsonObjMemory["fs_used"] = new JSONValue((int)FSCom.usedBytes()); jsonObjMemory["fs_free"] = new JSONValue(int(FSCom.totalBytes() - FSCom.usedBytes())); diff --git a/src/modules/NodeInfoModule.cpp b/src/modules/NodeInfoModule.cpp index cf8c17c3b..09819dab1 100644 --- a/src/modules/NodeInfoModule.cpp +++ b/src/modules/NodeInfoModule.cpp @@ -12,7 +12,7 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes { auto p = *pptr; - nodeDB.updateUser(getFrom(&mp), p); + bool hasChanged = nodeDB.updateUser(getFrom(&mp), p); bool wasBroadcast = mp.to == NODENUM_BROADCAST; @@ -23,6 +23,10 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes screen->print(lcd.c_str()); } + // if user has changed while packet was not for us, inform phone + if (hasChanged && !wasBroadcast && mp.to != nodeDB.getNodeNum()) + service.sendToPhone(packetPool.allocCopy(mp)); + // LOG_DEBUG("did handleReceived\n"); return false; // Let others look at this message also if they want } diff --git a/src/modules/Telemetry/Sensor/BME680Sensor.cpp b/src/modules/Telemetry/Sensor/BME680Sensor.cpp index f05246d52..df86da1bd 100644 --- a/src/modules/Telemetry/Sensor/BME680Sensor.cpp +++ b/src/modules/Telemetry/Sensor/BME680Sensor.cpp @@ -1,18 +1,26 @@ #include "BME680Sensor.h" #include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "FSCommon.h" #include "TelemetrySensor.h" #include "configuration.h" -#include BME680Sensor::BME680Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BME680, "BME680") {} int32_t BME680Sensor::runOnce() { - LOG_INFO("Init sensor: %s\n", sensorName); + LOG_INFO("Init sensor: %s with the BSEC Library\n", sensorName); if (!hasSensor()) { return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; } - status = bme680.begin(nodeTelemetrySensorsMap[sensorType]); + bme680.begin(nodeTelemetrySensorsMap[sensorType], Wire); + if (bme680.bsecStatus == BSEC_OK) { + bme680.setConfig(bsec_config_iaq); + loadState(); + bme680.updateSubscription(sensorList, 13, BSEC_SAMPLE_RATE_LP); + status = 1; + } else { + status = 0; + } return initI2CSensor(); } @@ -21,11 +29,76 @@ void BME680Sensor::setup() {} bool BME680Sensor::getMetrics(meshtastic_Telemetry *measurement) { - bme680.performReading(); + bme680.run(); measurement->variant.environment_metrics.temperature = bme680.temperature; measurement->variant.environment_metrics.relative_humidity = bme680.humidity; measurement->variant.environment_metrics.barometric_pressure = bme680.pressure / 100.0F; - measurement->variant.environment_metrics.gas_resistance = bme680.gas_resistance / 1000.0; - + measurement->variant.environment_metrics.gas_resistance = bme680.gasResistance / 1000.0; + // Check if we need to save state to filesystem (every STATE_SAVE_PERIOD ms) + updateState(); return true; +} + +void BME680Sensor::loadState() +{ +#ifdef FSCom + auto file = FSCom.open(bsecConfigFileName, FILE_O_READ); + if (file) { + file.read((uint8_t *)&bsecState, BSEC_MAX_STATE_BLOB_SIZE); + file.close(); + bme680.setState(bsecState); + LOG_INFO("%s state read from %s.\n", sensorName, bsecConfigFileName); + } else { + LOG_INFO("No %s state found (File: %s).\n", sensorName, bsecConfigFileName); + } +#else + LOG_ERROR("ERROR: Filesystem not implemented\n"); +#endif +} + +void BME680Sensor::updateState() +{ +#ifdef FSCom + bool update = false; + if (stateUpdateCounter == 0) { + /* First state update when IAQ accuracy is >= 3 */ + if (bme680.iaqAccuracy >= 3) { + LOG_DEBUG("%s state update IAQ accuracy %u >= 3\n", sensorName, bme680.iaqAccuracy); + update = true; + stateUpdateCounter++; + } else { + LOG_DEBUG("%s not updated, IAQ accuracy is %u >= 3\n", sensorName, bme680.iaqAccuracy); + } + } else { + /* Update every STATE_SAVE_PERIOD minutes */ + if ((stateUpdateCounter * STATE_SAVE_PERIOD) < millis()) { + LOG_DEBUG("%s state update every %d minutes\n", sensorName, STATE_SAVE_PERIOD); + update = true; + stateUpdateCounter++; + } + } + + if (update) { + bme680.getState(bsecState); + std::string filenameTmp = bsecConfigFileName; + filenameTmp += ".tmp"; + auto file = FSCom.open(bsecConfigFileName, FILE_O_WRITE); + if (file) { + LOG_INFO("%s state write to %s.\n", sensorName, bsecConfigFileName); + file.write((uint8_t *)&bsecState, BSEC_MAX_STATE_BLOB_SIZE); + file.flush(); + file.close(); + // brief window of risk here ;-) + if (FSCom.exists(bsecConfigFileName) && !FSCom.remove(bsecConfigFileName)) + LOG_WARN("Can't remove old state file\n"); + if (!renameFile(filenameTmp.c_str(), bsecConfigFileName)) + LOG_ERROR("Error: can't rename new state file\n"); + + } else { + LOG_INFO("Can't write %s state (File: %s).\n", sensorName, bsecConfigFileName); + } + } +#else + LOG_ERROR("ERROR: Filesystem not implemented\n"); +#endif } \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/BME680Sensor.h b/src/modules/Telemetry/Sensor/BME680Sensor.h index d59374803..74aff835a 100644 --- a/src/modules/Telemetry/Sensor/BME680Sensor.h +++ b/src/modules/Telemetry/Sensor/BME680Sensor.h @@ -1,14 +1,38 @@ #include "../mesh/generated/meshtastic/telemetry.pb.h" #include "TelemetrySensor.h" -#include +#include + +#define STATE_SAVE_PERIOD UINT32_C(360 * 60 * 1000) // That's 6 hours worth of millis() + +const uint8_t bsec_config_iaq[] = { +#include +}; class BME680Sensor : virtual public TelemetrySensor { private: - Adafruit_BME680 bme680; + Bsec bme680; protected: virtual void setup() override; + const char *bsecConfigFileName = "/prefs/bsec.dat"; + uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE] = {0}; + uint16_t stateUpdateCounter = 0; + bsec_virtual_sensor_t sensorList[13] = {BSEC_OUTPUT_IAQ, + BSEC_OUTPUT_STATIC_IAQ, + BSEC_OUTPUT_CO2_EQUIVALENT, + BSEC_OUTPUT_BREATH_VOC_EQUIVALENT, + BSEC_OUTPUT_RAW_TEMPERATURE, + BSEC_OUTPUT_RAW_PRESSURE, + BSEC_OUTPUT_RAW_HUMIDITY, + BSEC_OUTPUT_RAW_GAS, + BSEC_OUTPUT_STABILIZATION_STATUS, + BSEC_OUTPUT_RUN_IN_STATUS, + BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE, + BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, + BSEC_OUTPUT_GAS_PERCENTAGE}; + void loadState(); + void updateState(); public: BME680Sensor(); diff --git a/src/modules/esp32/RangeTestModule.cpp b/src/modules/esp32/RangeTestModule.cpp index 608e0868c..e8821f9a0 100644 --- a/src/modules/esp32/RangeTestModule.cpp +++ b/src/modules/esp32/RangeTestModule.cpp @@ -226,7 +226,7 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp) } else { LOG_ERROR("File write failed\n"); } - + fileToWrite.flush(); fileToWrite.close(); } @@ -275,6 +275,7 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp) // TODO: If quotes are found in the payload, it has to be escaped. fileToAppend.printf("\"%s\"\n", p.payload.bytes); + fileToAppend.flush(); fileToAppend.close(); return 1; diff --git a/src/modules/esp32/StoreForwardModule.cpp b/src/modules/esp32/StoreForwardModule.cpp index fbebc77e8..38e983669 100644 --- a/src/modules/esp32/StoreForwardModule.cpp +++ b/src/modules/esp32/StoreForwardModule.cpp @@ -5,6 +5,7 @@ #include "Router.h" #include "airtime.h" #include "configuration.h" +#include "memGet.h" #include "mesh-pb-constants.h" #include "mesh/generated/meshtastic/storeforward.pb.h" #include "modules/ModuleDev.h" @@ -63,8 +64,8 @@ void StoreForwardModule::populatePSRAM() https://learn.upesy.com/en/programmation/psram.html#psram-tab */ - LOG_DEBUG("*** Before PSRAM initilization: heap %d/%d PSRAM %d/%d\n", ESP.getFreeHeap(), ESP.getHeapSize(), - ESP.getFreePsram(), ESP.getPsramSize()); + LOG_DEBUG("*** Before PSRAM initilization: heap %d/%d PSRAM %d/%d\n", memGet.getFreeHeap(), memGet.getHeapSize(), + memGet.getFreePsram(), memGet.getPsramSize()); this->packetHistoryTXQueue = static_cast(ps_calloc(this->historyReturnMax, sizeof(PacketHistoryStruct))); @@ -72,13 +73,14 @@ void StoreForwardModule::populatePSRAM() /* Use a maximum of 2/3 the available PSRAM unless otherwise specified. Note: This needs to be done after every thing that would use PSRAM */ - uint32_t numberOfPackets = (this->records ? this->records : (((ESP.getFreePsram() / 3) * 2) / sizeof(PacketHistoryStruct))); + uint32_t numberOfPackets = + (this->records ? this->records : (((memGet.getFreePsram() / 3) * 2) / sizeof(PacketHistoryStruct))); this->records = numberOfPackets; this->packetHistory = static_cast(ps_calloc(numberOfPackets, sizeof(PacketHistoryStruct))); - LOG_DEBUG("*** After PSRAM initilization: heap %d/%d PSRAM %d/%d\n", ESP.getFreeHeap(), ESP.getHeapSize(), ESP.getFreePsram(), - ESP.getPsramSize()); + LOG_DEBUG("*** After PSRAM initilization: heap %d/%d PSRAM %d/%d\n", memGet.getFreeHeap(), memGet.getHeapSize(), + memGet.getFreePsram(), memGet.getPsramSize()); LOG_DEBUG("*** numberOfPackets for packetHistory - %u\n", numberOfPackets); } @@ -445,8 +447,8 @@ StoreForwardModule::StoreForwardModule() if ((config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER) || (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT)) { LOG_INFO("*** Initializing Store & Forward Module in Router mode\n"); - if (ESP.getPsramSize() > 0) { - if (ESP.getFreePsram() >= 1024 * 1024) { + if (memGet.getPsramSize() > 0) { + if (memGet.getFreePsram() >= 1024 * 1024) { // Do the startup here diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index 56bdf300f..bd1a85641 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -19,10 +19,6 @@ const int reconnectMax = 5; MQTT *mqtt; -std::string statusTopic = "msh/2/stat/"; -std::string cryptTopic = "msh/2/c/"; // msh/2/c/CHANNELID/NODEID -std::string jsonTopic = "msh/2/json/"; // msh/2/json/CHANNELID/NODEID - static MemoryDynamic staticMqttPool; Allocator &mqttPool = staticMqttPool; @@ -164,6 +160,16 @@ MQTT::MQTT() : concurrency::OSThread("mqtt"), pubSub(mqttClient), mqttQueue(MAX_ assert(!mqtt); mqtt = this; + if (*moduleConfig.mqtt.root) { + statusTopic = moduleConfig.mqtt.root + statusTopic; + cryptTopic = moduleConfig.mqtt.root + cryptTopic; + jsonTopic = moduleConfig.mqtt.root + jsonTopic; + } else { + statusTopic = "msh" + statusTopic; + cryptTopic = "msh" + cryptTopic; + jsonTopic = "msh" + jsonTopic; + } + pubSub.setCallback(mqttCallback); // preflightSleepObserver.observe(&preflightSleep); @@ -192,6 +198,26 @@ void MQTT::reconnect() mqttPassword = moduleConfig.mqtt.password; } +#if HAS_WIFI && !defined(ARCH_PORTDUINO) + if (moduleConfig.mqtt.tls_enabled) { + // change default for encrypted to 8883 + try { + serverPort = 8883; + wifiSecureClient.setInsecure(); + + pubSub.setClient(wifiSecureClient); + LOG_INFO("Using TLS-encrypted session\n"); + } catch (const std::exception &e) { + LOG_ERROR("MQTT ERROR: %s\n", e.what()); + } + } else { + LOG_INFO("Using non-TLS-encrypted session\n"); + pubSub.setClient(mqttClient); + } +#else + pubSub.setClient(mqttClient); +#endif + String server = String(serverAddr); int delimIndex = server.indexOf(':'); if (delimIndex > 0) { @@ -528,4 +554,4 @@ std::string MQTT::downstreamPacketToJson(meshtastic_MeshPacket *mp) delete value; return jsonStr; -} +} \ No newline at end of file diff --git a/src/mqtt/MQTT.h b/src/mqtt/MQTT.h index 2b38868be..1e626c3e0 100644 --- a/src/mqtt/MQTT.h +++ b/src/mqtt/MQTT.h @@ -8,6 +8,9 @@ #include #if HAS_WIFI #include +#if !defined(ARCH_PORTDUINO) +#include +#endif #endif #if HAS_ETHERNET #include @@ -23,9 +26,11 @@ class MQTT : private concurrency::OSThread { // supposedly the current version is busted: // http://www.iotsharing.com/2017/08/how-to-use-esp32-mqtts-with-mqtts-mosquitto-broker-tls-ssl.html - // WiFiClientSecure wifiClient; #if HAS_WIFI WiFiClient mqttClient; +#if !defined(ARCH_PORTDUINO) + WiFiClientSecure wifiSecureClient; +#endif #endif #if HAS_ETHERNET EthernetClient mqttClient; @@ -64,6 +69,9 @@ class MQTT : private concurrency::OSThread virtual int32_t runOnce() override; private: + std::string statusTopic = "/2/stat/"; + std::string cryptTopic = "/2/c/"; // msh/2/c/CHANNELID/NODEID + std::string jsonTopic = "/2/json/"; // msh/2/json/CHANNELID/NODEID /** return true if we have a channel that wants uplink/downlink */ bool wantsLink() const; @@ -87,4 +95,4 @@ class MQTT : private concurrency::OSThread void mqttInit(); -extern MQTT *mqtt; +extern MQTT *mqtt; \ No newline at end of file diff --git a/src/platform/esp32/main-esp32.cpp b/src/platform/esp32/main-esp32.cpp index 645132f38..4cb7f4443 100644 --- a/src/platform/esp32/main-esp32.cpp +++ b/src/platform/esp32/main-esp32.cpp @@ -162,7 +162,7 @@ void esp32Loop() // radio.radioIf.canSleep(); } -void cpuDeepSleep(uint64_t msecToWake) +void cpuDeepSleep(uint32_t msecToWake) { /* Some ESP32 IOs have internal pullups or pulldowns, which are enabled by default. @@ -202,7 +202,7 @@ void cpuDeepSleep(uint64_t msecToWake) #ifdef BUTTON_PIN // Only GPIOs which are have RTC functionality can be used in this bit map: 0,2,4,12-15,25-27,32-39. #if SOC_RTCIO_HOLD_SUPPORTED - uint64_t gpioMask = (1ULL << BUTTON_PIN); + uint64_t gpioMask = (1ULL << config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN); #endif #ifdef BUTTON_NEED_PULLUP diff --git a/src/platform/nrf52/NRF52Bluetooth.cpp b/src/platform/nrf52/NRF52Bluetooth.cpp index 59d11717a..044b57ae6 100644 --- a/src/platform/nrf52/NRF52Bluetooth.cpp +++ b/src/platform/nrf52/NRF52Bluetooth.cpp @@ -92,12 +92,12 @@ void startAdv(void) Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); // IncludeService UUID - Bluefruit.ScanResponse.addService(meshBleService); + // Bluefruit.ScanResponse.addService(meshBleService); Bluefruit.ScanResponse.addTxPower(); Bluefruit.ScanResponse.addName(); // Include Name - Bluefruit.Advertising.addName(); + // Bluefruit.Advertising.addName(); Bluefruit.Advertising.addService(meshBleService); /* Start Advertising diff --git a/src/platform/nrf52/hardfault.cpp b/src/platform/nrf52/hardfault.cpp index 13a4ee046..7b7a718b8 100644 --- a/src/platform/nrf52/hardfault.cpp +++ b/src/platform/nrf52/hardfault.cpp @@ -90,7 +90,7 @@ extern "C" void HardFault_Handler(void) asm volatile(" mrs r0,msp\n" " b HardFault_Impl \n"); } -#else +#elif !defined(ARCH_NRF52) /* The prototype shows it is a naked function - in effect this is just an assembly function. */ diff --git a/src/platform/nrf52/main-nrf52.cpp b/src/platform/nrf52/main-nrf52.cpp index 1cbe05631..36ddefeb4 100644 --- a/src/platform/nrf52/main-nrf52.cpp +++ b/src/platform/nrf52/main-nrf52.cpp @@ -155,7 +155,7 @@ void nrf52Setup() nRFCrypto.end(); } -void cpuDeepSleep(uint64_t msecToWake) +void cpuDeepSleep(uint32_t msecToWake) { // FIXME, configure RTC or button press to wake us // FIXME, power down SPI, I2C, RAMs diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index 144f5e0e3..af38b61a0 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -16,7 +16,7 @@ void setBluetoothEnable(bool on) // not needed } -void cpuDeepSleep(uint64_t msecs) +void cpuDeepSleep(uint32_t msecs) { notImplemented("cpuDeepSleep"); } diff --git a/src/platform/rp2040/main-rp2040.cpp b/src/platform/rp2040/main-rp2040.cpp index 1de8c5b68..af200f961 100644 --- a/src/platform/rp2040/main-rp2040.cpp +++ b/src/platform/rp2040/main-rp2040.cpp @@ -7,7 +7,7 @@ void setBluetoothEnable(bool on) // not needed } -void cpuDeepSleep(uint64_t msecs) +void cpuDeepSleep(uint32_t msecs) { // not needed } diff --git a/src/platform/stm32wl/main-stm32wl.cpp b/src/platform/stm32wl/main-stm32wl.cpp index 147408441..8ebcb029e 100644 --- a/src/platform/stm32wl/main-stm32wl.cpp +++ b/src/platform/stm32wl/main-stm32wl.cpp @@ -15,7 +15,7 @@ void getMacAddr(uint8_t *dmac) dmac[i] = i; } -void cpuDeepSleep(uint64_t msecToWake) {} +void cpuDeepSleep(uint32_t msecToWake) {} /* pacify libc_nano */ extern "C" { diff --git a/src/sleep.cpp b/src/sleep.cpp index e3f042a27..c25e3473e 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -19,6 +19,10 @@ esp_sleep_source_t wakeCause; // the reason we booted this time #endif +#ifndef INCLUDE_vTaskSuspend +#define INCLUDE_vTaskSuspend 0 +#endif + #ifdef HAS_PMU #include "XPowersLibInterface.hpp" extern XPowersLibInterface *PMU; @@ -201,9 +205,13 @@ void doGPSpowersave(bool on) #endif } -void doDeepSleep(uint64_t msecToWake) +void doDeepSleep(uint32_t msecToWake) { - LOG_INFO("Entering deep sleep for %lu seconds\n", msecToWake / 1000); + if (INCLUDE_vTaskSuspend && (msecToWake == portMAX_DELAY)) { + LOG_INFO("Entering deep sleep forever\n"); + } else { + LOG_INFO("Entering deep sleep for %u seconds\n", msecToWake / 1000); + } // not using wifi yet, but once we are this is needed to shutoff the radio hw // esp_wifi_stop(); @@ -301,7 +309,8 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r // assert(esp_sleep_enable_uart_wakeup(0) == ESP_OK); #endif #ifdef BUTTON_PIN - esp_sleep_enable_ext0_wakeup((gpio_num_t)BUTTON_PIN, LOW); // when user presses, this button goes low + esp_sleep_enable_ext0_wakeup((gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN), + LOW); // when user presses, this button goes low #endif #if defined(LORA_DIO1) && (LORA_DIO1 != RADIOLIB_NC) gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL); // SX126x/SX128x interrupt, active high @@ -330,7 +339,8 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); #ifdef BUTTON_PIN if (cause == ESP_SLEEP_WAKEUP_GPIO) - LOG_INFO("Exit light sleep gpio: btn=%d\n", !digitalRead(BUTTON_PIN)); + LOG_INFO("Exit light sleep gpio: btn=%d\n", + !digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN)); #endif return cause; diff --git a/src/sleep.h b/src/sleep.h index af59a8dad..a4b8f37b5 100644 --- a/src/sleep.h +++ b/src/sleep.h @@ -4,7 +4,7 @@ #include "Observer.h" #include "configuration.h" -void doDeepSleep(uint64_t msecToWake), cpuDeepSleep(uint64_t msecToWake); +void doDeepSleep(uint32_t msecToWake), cpuDeepSleep(uint32_t msecToWake); #ifdef ARCH_ESP32 #include "esp_sleep.h" diff --git a/src/xmodem.cpp b/src/xmodem.cpp index f8b5084dc..e8727c468 100644 --- a/src/xmodem.cpp +++ b/src/xmodem.cpp @@ -142,12 +142,14 @@ void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket) case meshtastic_XModem_Control_EOT: // End of transmission sendControl(meshtastic_XModem_Control_ACK); + file.flush(); file.close(); isReceiving = false; break; case meshtastic_XModem_Control_CAN: // Cancel transmission and remove file sendControl(meshtastic_XModem_Control_ACK); + file.flush(); file.close(); FSCom.remove(filename); isReceiving = false; diff --git a/variants/MakePython_nRF52840_eink/platformio.ini b/variants/MakePython_nRF52840_eink/platformio.ini index 825566146..9ed5a8594 100644 --- a/variants/MakePython_nRF52840_eink/platformio.ini +++ b/variants/MakePython_nRF52840_eink/platformio.ini @@ -7,7 +7,7 @@ build_flags = ${nrf52840_base.build_flags} -Ivariants/MakePython_nRF52840_eink - build_src_filter = ${nrf52_base.build_src_filter} +<../variants/MakePython_nRF52840_eink> lib_deps = ${nrf52840_base.lib_deps} - caveman99/ESP32 Codec2@^1.0.1 + https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f zinggjm/GxEPD2@^1.4.9 debug_tool = jlink upload_port = /dev/ttyACM4 diff --git a/variants/MakePython_nRF52840_oled/platformio.ini b/variants/MakePython_nRF52840_oled/platformio.ini index 35011fb09..9332bd786 100644 --- a/variants/MakePython_nRF52840_oled/platformio.ini +++ b/variants/MakePython_nRF52840_oled/platformio.ini @@ -6,5 +6,5 @@ build_flags = ${nrf52840_base.build_flags} -Ivariants/MakePython_nRF52840_oled - build_src_filter = ${nrf52_base.build_src_filter} +<../variants/MakePython_nRF52840_oled> lib_deps = ${nrf52840_base.lib_deps} - caveman99/ESP32 Codec2@^1.0.1 + https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f debug_tool = jlink diff --git a/variants/my_esp32s3_diy_eink/platformio.ini b/variants/my_esp32s3_diy_eink/platformio.ini index 01376f256..8405f784e 100644 --- a/variants/my_esp32s3_diy_eink/platformio.ini +++ b/variants/my_esp32s3_diy_eink/platformio.ini @@ -12,7 +12,6 @@ platform_packages = tool-esptoolpy@^1.40500.0 lib_deps = ${esp32_base.lib_deps} - caveman99/ESP32 Codec2@^1.0.1 zinggjm/GxEPD2@^1.5.1 adafruit/Adafruit NeoPixel@^1.10.7 build_unflags = -DARDUINO_USB_MODE=1 diff --git a/variants/my_esp32s3_diy_oled/platformio.ini b/variants/my_esp32s3_diy_oled/platformio.ini index 189e87fba..1430dfd96 100644 --- a/variants/my_esp32s3_diy_oled/platformio.ini +++ b/variants/my_esp32s3_diy_oled/platformio.ini @@ -12,7 +12,6 @@ platform_packages = tool-esptoolpy@^1.40500.0 lib_deps = ${esp32_base.lib_deps} - caveman99/ESP32 Codec2@^1.0.1 adafruit/Adafruit NeoPixel@^1.10.7 build_unflags = -DARDUINO_USB_MODE=1 build_flags = diff --git a/variants/tlora_t3s3_v1/platformio.ini b/variants/tlora_t3s3_v1/platformio.ini index 568e8af42..bef57c3b4 100644 --- a/variants/tlora_t3s3_v1/platformio.ini +++ b/variants/tlora_t3s3_v1/platformio.ini @@ -2,9 +2,6 @@ extends = esp32s3_base board = tlora-t3s3-v1 upload_protocol = esp-builtin -lib_deps = - ${esp32_base.lib_deps} - caveman99/ESP32 Codec2@^1.0.1 build_flags = ${esp32_base.build_flags} -D TLORA_T3S3_V1 -I variants/tlora_t3s3_v1 \ No newline at end of file diff --git a/variants/tlora_v2_1_18/platformio.ini b/variants/tlora_v2_1_18/platformio.ini index c61b8a28c..01741ca13 100644 --- a/variants/tlora_v2_1_18/platformio.ini +++ b/variants/tlora_v2_1_18/platformio.ini @@ -1,9 +1,6 @@ [env:tlora-v2-1-1.8] extends = esp32_base board = ttgo-lora32-v21 -lib_deps = - ${esp32_base.lib_deps} - caveman99/ESP32 Codec2@^1.0.1 build_flags = ${esp32_base.build_flags} -D TLORA_V2_1_18 -I variants/tlora_v2_1_18 \ No newline at end of file diff --git a/version.properties b/version.properties index b26a5f4c0..253a4d545 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 1 -build = 7 +build = 10