From f9798b7dda576c65fb6830796a4d3e64217df104 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Tue, 8 Aug 2023 08:05:43 -0500 Subject: [PATCH 01/24] Bump to 2.2 --- version.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.properties b/version.properties index 1c45cbf4b..3909d8d04 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 -minor = 1 -build = 23 +minor = 2 +build = 0 From 0fe99b0caa94d51cc4794a1475b873968b854f8c Mon Sep 17 00:00:00 2001 From: mverch67 Date: Tue, 8 Aug 2023 18:06:39 +0200 Subject: [PATCH 02/24] T-Watch fixes --- boards/t-watch-s3.json | 2 +- src/PowerFSM.cpp | 3 ++- src/graphics/TFTDisplay.cpp | 40 ++++++++++++++++++----------- src/graphics/TFTDisplay.h | 3 +++ src/input/TouchScreenBase.cpp | 2 +- src/input/TouchScreenImpl1.cpp | 5 ++++ src/modules/CannedMessageModule.cpp | 4 +-- variants/t-deck/variant.h | 1 + variants/t-watch-s3/variant.h | 1 + 9 files changed, 41 insertions(+), 20 deletions(-) diff --git a/boards/t-watch-s3.json b/boards/t-watch-s3.json index d4c9f2abd..e86917df6 100644 --- a/boards/t-watch-s3.json +++ b/boards/t-watch-s3.json @@ -15,7 +15,7 @@ "f_cpu": "240000000L", "f_flash": "80000000L", "flash_mode": "dio", - "hwids": [["0X303A", "0x1001"]], + "hwids": [["0x303A", "0x1001"]], "mcu": "esp32s3", "variant": "t-watch-s3" }, diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 6c6069365..a873e93c7 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -297,7 +297,8 @@ void PowerFSM_setup() powerFSM.add_transition(&stateLS, &stateON, EVENT_INPUT, NULL, "Input Device"); powerFSM.add_transition(&stateNB, &stateON, EVENT_INPUT, NULL, "Input Device"); powerFSM.add_transition(&stateDARK, &stateON, EVENT_INPUT, NULL, "Input Device"); - powerFSM.add_transition(&stateON, &stateON, EVENT_INPUT, NULL, "Input Device"); // restarts the sleep timer + powerFSM.add_transition(&stateON, &stateON, EVENT_INPUT, NULL, "Input Device"); // restarts the sleep timer + powerFSM.add_transition(&statePOWER, &statePOWER, EVENT_INPUT, NULL, "Input Device"); // restarts the sleep timer powerFSM.add_transition(&stateDARK, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing"); powerFSM.add_transition(&stateON, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing"); diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index 186887457..08ed66337 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -148,16 +148,16 @@ class LGFX : public lgfx::LGFX_Device // The following setting values ​​are general initial values ​​for each panel, so please comment out any // unknown items and try them. - cfg.panel_width = TFT_WIDTH; // actual displayable width - cfg.panel_height = TFT_HEIGHT; // actual displayable height - cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction - cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction - cfg.offset_rotation = 0; // Rotation direction value offset 0~7 (4~7 is mirrored) - cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout - cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read - cfg.readable = true; // Set to true if data can be read - cfg.invert = true; // Set to true if the light/darkness of the panel is reversed - cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped + cfg.panel_width = TFT_WIDTH; // actual displayable width + cfg.panel_height = TFT_HEIGHT; // actual displayable height + cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction + cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction + cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored) + cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout + cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read + cfg.readable = true; // Set to true if data can be read + cfg.invert = true; // Set to true if the light/darkness of the panel is reversed + cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped cfg.dlen_16bit = false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.) @@ -192,7 +192,7 @@ class LGFX : public lgfx::LGFX_Device cfg.y_max = TFT_WIDTH - 1; cfg.pin_int = SCREEN_TOUCH_INT; cfg.bus_shared = true; - cfg.offset_rotation = 0; + cfg.offset_rotation = TFT_OFFSET_ROTATION; // cfg.freq = 2500000; // I2C @@ -389,6 +389,14 @@ void TFTDisplay::sendCommand(uint8_t com) // Drop all other commands to device (we just update the buffer) } +void TFTDisplay::flipScreenVertically() +{ +#if defined(T_WATCH_S3) + LOG_DEBUG("Flip TFT vertically\n"); // T-Watch S3 right-handed orientation + tft.setRotation(0); +#endif +} + bool TFTDisplay::hasTouch(void) { #ifndef M5STACK @@ -424,10 +432,12 @@ bool TFTDisplay::connect() #endif tft.init(); -#if defined(T_DECK) - tft.setRotation(1); // M5Stack/T-Deck have the TFT in landscape -#elif defined(M5STACK) || defined(T_WATCH_S3) - tft.setRotation(0); // T-Watch S3 has the TFT in portrait +#if defined(M5STACK) + tft.setRotation(0); +#elif defined(T_DECK) + tft.setRotation(1); // T-Deck has the TFT in landscape +#elif defined(T_WATCH_S3) + tft.setRotation(2); // T-Watch S3 left-handed orientation #else tft.setRotation(3); // Orient horizontal and wide underneath the silkscreen name label #endif diff --git a/src/graphics/TFTDisplay.h b/src/graphics/TFTDisplay.h index dee31acf1..8c9a9b62e 100644 --- a/src/graphics/TFTDisplay.h +++ b/src/graphics/TFTDisplay.h @@ -22,6 +22,9 @@ class TFTDisplay : public OLEDDisplay // Write the buffer to the display memory virtual void display(void) override; + // Turn the display upside down + virtual void flipScreenVertically(); + // Touch screen (static handlers) static bool hasTouch(void); static bool getTouch(int16_t *x, int16_t *y); diff --git a/src/input/TouchScreenBase.cpp b/src/input/TouchScreenBase.cpp index dad1bb56c..2f361ac4c 100644 --- a/src/input/TouchScreenBase.cpp +++ b/src/input/TouchScreenBase.cpp @@ -40,13 +40,13 @@ int32_t TouchScreenBase::runOnce() int16_t x, y; bool touched = getTouch(x, y); if (touched) { - hapticFeedback(); this->setInterval(20); _last_x = x; _last_y = y; } if (touched != _touchedOld) { if (touched) { + hapticFeedback(); _state = TOUCH_EVENT_OCCURRED; _start = millis(); _first_x = x; diff --git a/src/input/TouchScreenImpl1.cpp b/src/input/TouchScreenImpl1.cpp index 9a7ecd4a2..b3152c88a 100644 --- a/src/input/TouchScreenImpl1.cpp +++ b/src/input/TouchScreenImpl1.cpp @@ -1,5 +1,6 @@ #include "TouchScreenImpl1.h" #include "InputBroker.h" +#include "PowerFSM.h" #include "configuration.h" TouchScreenImpl1 *touchScreenImpl1; @@ -61,6 +62,10 @@ void TouchScreenImpl1::onEvent(const TouchEvent &event) e.inputEvent = static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL); break; } + case TOUCH_ACTION_TAP: { + powerFSM.trigger(EVENT_INPUT); + break; + } default: return; } diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index 3ca718e99..952e9065a 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -221,8 +221,8 @@ void CannedMessageModule::sendText(NodeNum dest, const char *message, bool wantR p->decoded.payload.size = strlen(message); memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size); if (moduleConfig.canned_message.send_bell) { - p->decoded.payload.bytes[p->decoded.payload.size - 1] = 7; // Bell character - p->decoded.payload.bytes[p->decoded.payload.size] = '\0'; // Bell character + p->decoded.payload.bytes[p->decoded.payload.size] = 7; // Bell character + p->decoded.payload.bytes[p->decoded.payload.size + 1] = '\0'; // Bell character p->decoded.payload.size++; } diff --git a/variants/t-deck/variant.h b/variants/t-deck/variant.h index 04f20fa74..9613d882a 100644 --- a/variants/t-deck/variant.h +++ b/variants/t-deck/variant.h @@ -15,6 +15,7 @@ #define TFT_WIDTH 240 #define TFT_OFFSET_X 0 #define TFT_OFFSET_Y 0 +#define TFT_OFFSET_ROTATION 0 #define SCREEN_ROTATE #define SCREEN_TRANSITION_FRAMERATE 5 diff --git a/variants/t-watch-s3/variant.h b/variants/t-watch-s3/variant.h index 8c0fc9122..dc363603b 100644 --- a/variants/t-watch-s3/variant.h +++ b/variants/t-watch-s3/variant.h @@ -15,6 +15,7 @@ #define TFT_WIDTH 240 #define TFT_OFFSET_X 0 #define TFT_OFFSET_Y 0 +#define TFT_OFFSET_ROTATION 2 #define SCREEN_ROTATE #define SCREEN_TRANSITION_FRAMERATE 5 // fps From 746d7268a2af9d731dc4f8d757cf5f8d02b4ef5d Mon Sep 17 00:00:00 2001 From: mverch67 Date: Tue, 8 Aug 2023 18:51:11 +0200 Subject: [PATCH 03/24] fix picomputer --- variants/picomputer-s3/variant.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/variants/picomputer-s3/variant.h b/variants/picomputer-s3/variant.h index 0f416efe0..03d8b8440 100644 --- a/variants/picomputer-s3/variant.h +++ b/variants/picomputer-s3/variant.h @@ -39,16 +39,17 @@ #define TFT_WIDTH 240 #define TFT_OFFSET_X 0 #define TFT_OFFSET_Y 0 +#define TFT_OFFSET_ROTATION 0 #define SCREEN_ROTATE #define SCREEN_TRANSITION_FRAMERATE 5 #define INPUTBROKER_MATRIX_TYPE 1 -#define KEYS_COLS \ - { \ - 44, 47, 17, 15, 13, 41 \ +#define KEYS_COLS \ + { \ + 44, 47, 17, 15, 13, 41 \ } -#define KEYS_ROWS \ - { \ - 12, 16, 42, 18, 14, 7 \ +#define KEYS_ROWS \ + { \ + 12, 16, 42, 18, 14, 7 \ } From 1d0ac2caf73bc04bd517e12cc44eaa2ecde8639f Mon Sep 17 00:00:00 2001 From: mverch67 Date: Tue, 8 Aug 2023 18:55:00 +0200 Subject: [PATCH 04/24] trunk fmt --- variants/picomputer-s3/variant.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/variants/picomputer-s3/variant.h b/variants/picomputer-s3/variant.h index 03d8b8440..197eb3da1 100644 --- a/variants/picomputer-s3/variant.h +++ b/variants/picomputer-s3/variant.h @@ -45,11 +45,11 @@ #define INPUTBROKER_MATRIX_TYPE 1 -#define KEYS_COLS \ - { \ - 44, 47, 17, 15, 13, 41 \ +#define KEYS_COLS \ + { \ + 44, 47, 17, 15, 13, 41 \ } -#define KEYS_ROWS \ - { \ - 12, 16, 42, 18, 14, 7 \ +#define KEYS_ROWS \ + { \ + 12, 16, 42, 18, 14, 7 \ } From 1986267d65d95ee0c2a9e5592716c7e90f57323e Mon Sep 17 00:00:00 2001 From: mverch67 Date: Tue, 8 Aug 2023 20:02:29 +0200 Subject: [PATCH 05/24] check payload size --- src/modules/CannedMessageModule.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index 5f6a374a1..0a3aaafb4 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -224,7 +224,7 @@ void CannedMessageModule::sendText(NodeNum dest, const char *message, bool wantR p->want_ack = true; p->decoded.payload.size = strlen(message); memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size); - if (moduleConfig.canned_message.send_bell) { + if (moduleConfig.canned_message.send_bell && p->decoded.payload.size < meshtastic_Constants_DATA_PAYLOAD_LEN) { p->decoded.payload.bytes[p->decoded.payload.size] = 7; // Bell character p->decoded.payload.bytes[p->decoded.payload.size + 1] = '\0'; // Bell character p->decoded.payload.size++; From 616553ed7200825a13cc4cb5000bf709d6aeaf01 Mon Sep 17 00:00:00 2001 From: mverch67 Date: Tue, 8 Aug 2023 20:14:12 +0200 Subject: [PATCH 06/24] doing the math :) --- src/modules/CannedMessageModule.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index 0a3aaafb4..314624a13 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -398,9 +398,10 @@ int32_t CannedMessageModule::runOnce() this->freetext.substring(0, this->cursor) + this->payload + this->freetext.substring(this->cursor); } this->cursor += 1; - if (this->freetext.length() > meshtastic_Constants_DATA_PAYLOAD_LEN) { - this->cursor = meshtastic_Constants_DATA_PAYLOAD_LEN; - this->freetext = this->freetext.substring(0, meshtastic_Constants_DATA_PAYLOAD_LEN); + uint16_t maxChars = meshtastic_Constants_DATA_PAYLOAD_LEN - (moduleConfig.canned_message.send_bell ? 1 : 0); + if (this->freetext.length() > maxChars) { + this->cursor = maxChars; + this->freetext = this->freetext.substring(0, maxChars); } break; } @@ -499,7 +500,8 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st } display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest)); // used chars right aligned - snprintf(buffer, sizeof(buffer), "%d left", meshtastic_Constants_DATA_PAYLOAD_LEN - this->freetext.length()); + uint16_t charsLeft = meshtastic_Constants_DATA_PAYLOAD_LEN - this->freetext.length() - (moduleConfig.canned_message.send_bell ? 1 : 0); + snprintf(buffer, sizeof(buffer), "%d left", charsLeft); display->drawString(x + display->getWidth() - display->getStringWidth(buffer), y + 0, buffer); if (this->destSelect) { display->drawString(x + display->getWidth() - display->getStringWidth(buffer) - 1, y + 0, buffer); From dd69de9f320b04bd4a23f2766222448b31ab30cf Mon Sep 17 00:00:00 2001 From: mverch67 Date: Tue, 8 Aug 2023 20:21:20 +0200 Subject: [PATCH 07/24] trunk fmt --- src/modules/CannedMessageModule.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index 314624a13..71a9d746c 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -500,7 +500,8 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st } display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest)); // used chars right aligned - uint16_t charsLeft = meshtastic_Constants_DATA_PAYLOAD_LEN - this->freetext.length() - (moduleConfig.canned_message.send_bell ? 1 : 0); + uint16_t charsLeft = + meshtastic_Constants_DATA_PAYLOAD_LEN - this->freetext.length() - (moduleConfig.canned_message.send_bell ? 1 : 0); snprintf(buffer, sizeof(buffer), "%d left", charsLeft); display->drawString(x + display->getWidth() - display->getStringWidth(buffer), y + 0, buffer); if (this->destSelect) { From 2074c76780096497b3e85507acfcf1f26add2be0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 10 Aug 2023 05:53:55 -0500 Subject: [PATCH 08/24] [create-pull-request] automated change (#2697) Co-authored-by: thebentern --- version.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.properties b/version.properties index 3909d8d04..8cc16d822 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 2 -build = 0 +build = 1 From 9470d4694bd5510174c8e0898af57cbd6f528c7f Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Thu, 10 Aug 2023 11:21:35 -0500 Subject: [PATCH 09/24] Pickier parsing of NMEA to detect an L76K chip (#2699) Co-authored-by: Ben Meadors --- src/gps/GPS.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 62536505d..0e60d149e 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -884,7 +884,7 @@ GnssModel_t GPS::probe() int index = ver.indexOf("$"); if (index != -1) { ver = ver.substring(index); - if (ver.startsWith("$GPTXT,01,01,02")) { + if (ver.startsWith("$GPTXT,01,01,02,SW=")) { LOG_INFO("L76K GNSS init succeeded, using L76K GNSS Module\n"); return GNSS_MODEL_MTK; } From ede31a20806f6956af529da2e8b242d2e8a7d01f Mon Sep 17 00:00:00 2001 From: mverch67 Date: Fri, 11 Aug 2023 19:41:21 +0200 Subject: [PATCH 10/24] fix repeater crash --- src/graphics/Screen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index ce6b7d5dd..9586830c1 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1058,7 +1058,8 @@ void Screen::setup() nodeStatusObserver.observe(&nodeStatus->onNewStatus); if (textMessageModule) textMessageObserver.observe(textMessageModule); - inputObserver.observe(inputBroker); + if (inputBroker) + inputObserver.observe(inputBroker); // Modules can notify screen about refresh MeshModule::observeUIEvents(&uiFrameEventObserver); From 3d6fb13f9a4737be138ceb19c25a737660383207 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sat, 12 Aug 2023 06:43:13 -0500 Subject: [PATCH 11/24] Stop failing on low severity styling issues --- bin/check-all.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bin/check-all.sh b/bin/check-all.sh index e6db5b959..1475ac3ee 100755 --- a/bin/check-all.sh +++ b/bin/check-all.sh @@ -4,23 +4,23 @@ set -e -VERSION=`bin/buildinfo.py long` +VERSION=$(bin/buildinfo.py long) # The shell vars the build tool expects to find export APP_VERSION=$VERSION if [[ $# -gt 0 ]]; then - # can override which environment by passing arg - BOARDS="$@" + # can override which environment by passing arg + BOARDS="$@" else - BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631 rak4631_eink rak11200 t-echo pca10059_diy_eink" + BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631 rak4631_eink rak11200 t-echo pca10059_diy_eink" fi echo "BOARDS:${BOARDS}" CHECK="" for BOARD in $BOARDS; do - CHECK="${CHECK} -e ${BOARD}" + CHECK="${CHECK} -e ${BOARD}" done -pio check --flags "-DAPP_VERSION=${APP_VERSION} --suppressions-list=suppressions.txt" $CHECK --skip-packages --pattern="src/" --fail-on-defect=low --fail-on-defect=medium --fail-on-defect=high +pio check --flags "-DAPP_VERSION=${APP_VERSION} --suppressions-list=suppressions.txt" $CHECK --skip-packages --pattern="src/" --fail-on-defect=medium --fail-on-defect=high From 84ddfea49196756d0027a0c8342b6c6a43156a5f Mon Sep 17 00:00:00 2001 From: Manuel <71137295+mverch67@users.noreply.github.com> Date: Sat, 12 Aug 2023 16:28:58 +0200 Subject: [PATCH 12/24] try-fix: max nodes crash during boot (#2712) * try-fix: nodenum crash during boot * Revert "try-fix: nodenum crash during boot" This reverts commit 632012e197632aafdbd5ef09872622274e00bcc0. * try-fix: max nodes crash during boot --------- Co-authored-by: Ben Meadors --- src/mesh/NodeDB.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index e7526505a..47e1474b2 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -790,7 +790,8 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n) if (!lite) { if ((*numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfoLite_size * 3)) { - screen->print("warning: node_db_lite full! erasing oldest entry\n"); + if (screen) + screen->print("warning: node_db_lite full! erasing oldest entry\n"); // look for oldest node and erase it uint32_t oldest = UINT32_MAX; int oldestIndex = -1; From 6e0b6684eefe52dcd9bfcd743783f70ed5cd2a34 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sat, 12 Aug 2023 09:29:19 -0500 Subject: [PATCH 13/24] Extend node max to 100 and remove mesh_sds_timeout_secs (#2713) * Extend node max to 100 and remove mesh_sds_timeout_secs * Const pointers for you and you and you * Fixes and supressions * Missed it * uint * Resize * Derp --- protobufs | 2 +- src/PowerFSMThread.h | 2 +- src/graphics/Screen.cpp | 8 ++++---- src/mesh/MeshService.cpp | 2 +- src/mesh/NodeDB.cpp | 2 +- src/mesh/generated/meshtastic/config.pb.h | 14 +++----------- src/mesh/generated/meshtastic/deviceonly.pb.h | 10 +++++----- src/mesh/generated/meshtastic/localonly.pb.h | 2 +- src/mesh/generated/meshtastic/mesh.pb.h | 2 ++ src/mesh/http/ContentHandler.cpp | 7 ++----- src/modules/NeighborInfoModule.cpp | 8 ++++---- src/modules/NeighborInfoModule.h | 2 +- src/modules/PositionModule.cpp | 2 +- src/modules/SerialModule.cpp | 2 +- src/modules/TraceRouteModule.cpp | 2 +- src/modules/esp32/StoreForwardModule.cpp | 2 +- src/modules/esp32/StoreForwardModule.h | 2 +- src/mqtt/MQTT.cpp | 4 ++-- suppressions.txt | 5 ++++- 19 files changed, 37 insertions(+), 43 deletions(-) diff --git a/protobufs b/protobufs index d47300965..6320d6795 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit d47300965904a8d55d109327568e19a2eb9a12c0 +Subproject commit 6320d6795e5462da38ab0bdc3769163a0fac37c6 diff --git a/src/PowerFSMThread.h b/src/PowerFSMThread.h index 4ebc14a1e..541522f43 100644 --- a/src/PowerFSMThread.h +++ b/src/PowerFSMThread.h @@ -21,7 +21,7 @@ class PowerFSMThread : public OSThread /// If we are in power state we force the CPU to wake every 10ms to check for serial characters (we don't yet wake /// cpu for serial rx - FIXME) - auto state = powerFSM.getState(); + const auto state = powerFSM.getState(); canSleep = (state != &statePOWER) && (state != &stateSERIAL); if (powerStatus->getHasUSB()) { diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 9586830c1..53e2ea95f 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -374,7 +374,7 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state // the max length of this buffer is much longer than we can possibly print static char tempBuf[237]; - meshtastic_MeshPacket &mp = devicestate.rx_text_message; + const meshtastic_MeshPacket &mp = devicestate.rx_text_message; meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(getFrom(&mp)); // LOG_DEBUG("drawing text message from 0x%x: %s\n", mp.from, // mp.decoded.variant.data.decoded.bytes); @@ -490,7 +490,7 @@ static void drawBattery(OLEDDisplay *display, int16_t x, int16_t y, uint8_t *img } // Draw nodes status -static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, NodeStatus *nodeStatus) +static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const NodeStatus *nodeStatus) { char usersString[20]; snprintf(usersString, sizeof(usersString), "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal()); @@ -858,14 +858,14 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ bool hasNodeHeading = false; if (ourNode && hasValidPosition(ourNode)) { - meshtastic_PositionLite &op = ourNode->position; + const meshtastic_PositionLite &op = ourNode->position; float myHeading = estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i)); drawCompassNorth(display, compassX, compassY, myHeading); if (hasValidPosition(node)) { // display direction toward node hasNodeHeading = true; - meshtastic_PositionLite &p = node->position; + const meshtastic_PositionLite &p = node->position; float d = GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i)); diff --git a/src/mesh/MeshService.cpp b/src/mesh/MeshService.cpp index 90da7ea5c..96ea2f0a1 100644 --- a/src/mesh/MeshService.cpp +++ b/src/mesh/MeshService.cpp @@ -320,7 +320,7 @@ meshtastic_NodeInfoLite *MeshService::refreshLocalMeshNode() int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus) { // Update our local node info with our position (even if we don't decide to update anyone else) - meshtastic_NodeInfoLite *node = refreshLocalMeshNode(); + const meshtastic_NodeInfoLite *node = refreshLocalMeshNode(); meshtastic_Position pos = meshtastic_Position_init_default; if (newStatus->getHasLock()) { diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 47e1474b2..924d98698 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -765,7 +765,7 @@ void NodeDB::updateFrom(const meshtastic_MeshPacket &mp) uint8_t NodeDB::getMeshNodeChannel(NodeNum n) { - meshtastic_NodeInfoLite *info = getMeshNode(n); + const meshtastic_NodeInfoLite *info = getMeshNode(n); if (!info) { return 0; // defaults to PRIMARY } diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index 2bd1a177b..a02b41a76 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -292,12 +292,6 @@ typedef struct _meshtastic_Config_PowerConfig { The number of seconds for to wait before turning off BLE in No Bluetooth states 0 for default of 1 minute */ uint32_t wait_bluetooth_secs; - /* Deprecated in 2.1.X - Mesh Super Deep Sleep Timeout Seconds - While in Light Sleep if this value is exceeded we will lower into super deep sleep - for sds_secs (default 1 year) or a button press - 0 for default of two hours, MAXUINT for disabled */ - uint32_t mesh_sds_timeout_secs; /* Super Deep Sleep Seconds While in Light Sleep if mesh_sds_timeout_secs is exceeded we will lower into super deep sleep for this value (default 1 year) or a button press @@ -537,7 +531,7 @@ extern "C" { #define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}} #define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0} #define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0} +#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""} #define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0} #define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0} @@ -546,7 +540,7 @@ extern "C" { #define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}} #define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0} #define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0} +#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""} #define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0} #define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0} @@ -578,7 +572,6 @@ extern "C" { #define meshtastic_Config_PowerConfig_on_battery_shutdown_after_secs_tag 2 #define meshtastic_Config_PowerConfig_adc_multiplier_override_tag 3 #define meshtastic_Config_PowerConfig_wait_bluetooth_secs_tag 4 -#define meshtastic_Config_PowerConfig_mesh_sds_timeout_secs_tag 5 #define meshtastic_Config_PowerConfig_sds_secs_tag 6 #define meshtastic_Config_PowerConfig_ls_secs_tag 7 #define meshtastic_Config_PowerConfig_min_wake_secs_tag 8 @@ -683,7 +676,6 @@ X(a, STATIC, SINGULAR, BOOL, is_power_saving, 1) \ X(a, STATIC, SINGULAR, UINT32, on_battery_shutdown_after_secs, 2) \ X(a, STATIC, SINGULAR, FLOAT, adc_multiplier_override, 3) \ X(a, STATIC, SINGULAR, UINT32, wait_bluetooth_secs, 4) \ -X(a, STATIC, SINGULAR, UINT32, mesh_sds_timeout_secs, 5) \ X(a, STATIC, SINGULAR, UINT32, sds_secs, 6) \ X(a, STATIC, SINGULAR, UINT32, ls_secs, 7) \ X(a, STATIC, SINGULAR, UINT32, min_wake_secs, 8) \ @@ -781,7 +773,7 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg; #define meshtastic_Config_NetworkConfig_IpV4Config_size 20 #define meshtastic_Config_NetworkConfig_size 195 #define meshtastic_Config_PositionConfig_size 54 -#define meshtastic_Config_PowerConfig_size 46 +#define meshtastic_Config_PowerConfig_size 40 #define meshtastic_Config_size 198 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index 0c4b94c86..998b02bcc 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -151,7 +151,7 @@ typedef struct _meshtastic_DeviceState { meshtastic_NodeRemoteHardwarePin node_remote_hardware_pins[12]; /* New lite version of NodeDB to decrease memory footprint */ pb_size_t node_db_lite_count; - meshtastic_NodeInfoLite node_db_lite[80]; + meshtastic_NodeInfoLite node_db_lite[100]; } meshtastic_DeviceState; @@ -174,13 +174,13 @@ extern "C" { /* Initializer values for message structs */ -#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default, 0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}, 0, {meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default}} +#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default, 0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}, 0, {meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default, meshtastic_NodeInfoLite_init_default}} #define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_User_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0} #define meshtastic_PositionLite_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN} #define meshtastic_ChannelFile_init_default {0, {meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default}, 0} #define meshtastic_OEMStore_init_default {0, 0, {0, {0}}, _meshtastic_ScreenFonts_MIN, "", {0, {0}}, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default} #define meshtastic_NodeRemoteHardwarePin_init_default {0, false, meshtastic_RemoteHardwarePin_init_default} -#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero, 0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}, 0, {meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero}} +#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero, 0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}, 0, {meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero, meshtastic_NodeInfoLite_init_zero}} #define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0} #define meshtastic_PositionLite_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN} #define meshtastic_ChannelFile_init_zero {0, {meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero}, 0} @@ -313,10 +313,10 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg; /* Maximum encoded size of messages (where known) */ #define meshtastic_ChannelFile_size 638 -#define meshtastic_DeviceState_size 13774 +#define meshtastic_DeviceState_size 16854 #define meshtastic_NodeInfoLite_size 151 #define meshtastic_NodeRemoteHardwarePin_size 29 -#define meshtastic_OEMStore_size 3154 +#define meshtastic_OEMStore_size 3148 #define meshtastic_PositionLite_size 28 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index b7199a001..4c27e0b67 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -162,7 +162,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; #define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg /* Maximum encoded size of messages (where known) */ -#define meshtastic_LocalConfig_size 461 +#define meshtastic_LocalConfig_size 455 #define meshtastic_LocalModuleConfig_size 547 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 79800f3c8..060c18fe1 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -61,6 +61,8 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_NANO_G1_EXPLORER = 17, /* B&Q Consulting Nano G2 Ultra: https://wiki.uniteng.com/en/meshtastic/nano-g2-ultra */ meshtastic_HardwareModel_NANO_G2_ULTRA = 18, + /* LoRAType device: https://loratype.org/ */ + meshtastic_HardwareModel_LORA_TYPE = 19, /* B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station */ meshtastic_HardwareModel_STATION_G1 = 25, /* RAK11310 (RP2040 + SX1262) */ diff --git a/src/mesh/http/ContentHandler.cpp b/src/mesh/http/ContentHandler.cpp index acee9be0d..c54366f04 100644 --- a/src/mesh/http/ContentHandler.cpp +++ b/src/mesh/http/ContentHandler.cpp @@ -402,7 +402,6 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res) "href=/admin>admin"); return; - } else { res->setHeader("Content-Encoding", "gzip"); } @@ -438,7 +437,6 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res) file.close(); return; - } else { LOG_ERROR("This should not have happened...\n"); res->println("ERROR: This should not have happened..."); @@ -467,7 +465,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res) // first semicolon, if one exists: size_t semicolonPos = contentType.find(";"); if (semicolonPos != std::string::npos) { - contentType = contentType.substr(0, semicolonPos); + contentType.resize(semicolonPos); } // Now, we can decide based on the content type: @@ -581,7 +579,6 @@ void handleReport(HTTPRequest *req, HTTPResponse *res) res->setHeader("Content-Type", "application/json"); res->setHeader("Access-Control-Allow-Origin", "*"); res->setHeader("Access-Control-Allow-Methods", "GET"); - } else { res->setHeader("Content-Type", "text/html"); res->println("
");
@@ -857,4 +854,4 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
     JSONValue *value = new JSONValue(jsonObjOuter);
     res->print(value->Stringify().c_str());
     delete value;
-}
+}
\ No newline at end of file
diff --git a/src/modules/NeighborInfoModule.cpp b/src/modules/NeighborInfoModule.cpp
index 578b41b29..6d800f37e 100644
--- a/src/modules/NeighborInfoModule.cpp
+++ b/src/modules/NeighborInfoModule.cpp
@@ -35,7 +35,7 @@ void NeighborInfoModule::printNodeDBNodes(const char *header)
     LOG_DEBUG("----------------\n");
     LOG_DEBUG("DB contains %d nodes\n", num_nodes);
     for (int i = 0; i < num_nodes; i++) {
-        meshtastic_NodeInfoLite *dbEntry = nodeDB.getMeshNodeByIndex(i);
+        const meshtastic_NodeInfoLite *dbEntry = nodeDB.getMeshNodeByIndex(i);
         LOG_DEBUG("     Node %d: node_id=%d, snr=%.2f\n", i, dbEntry->num, dbEntry->snr);
     }
     LOG_DEBUG("----------------\n");
@@ -52,7 +52,7 @@ void NeighborInfoModule::printNodeDBNeighbors(const char *header)
     LOG_DEBUG("----------------\n");
     LOG_DEBUG("DB contains %d neighbors\n", num_neighbors);
     for (int i = 0; i < num_neighbors; i++) {
-        meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
+        const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
         LOG_DEBUG("     Node %d: node_id=%d, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
     }
     LOG_DEBUG("----------------\n");
@@ -164,7 +164,7 @@ size_t NeighborInfoModule::cleanUpNeighbors()
     }
 
     // Update the neighbor list
-    for (int i = 0; i < indices_to_remove.size(); i++) {
+    for (uint i = 0; i < indices_to_remove.size(); i++) {
         int index = indices_to_remove[i];
         LOG_DEBUG("Removing neighbor with node ID 0x%x\n", neighbors[index].node_id);
         for (int j = index; j < num_neighbors - 1; j++) {
@@ -245,7 +245,7 @@ void NeighborInfoModule::resetNeighbors()
     saveProtoForModule();
 }
 
-void NeighborInfoModule::updateNeighbors(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *np)
+void NeighborInfoModule::updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np)
 {
     // The last sent ID will be 0 if the packet is from the phone, which we don't count as
     // an edge. So we assume that if it's zero, then this packet is from our node.
diff --git a/src/modules/NeighborInfoModule.h b/src/modules/NeighborInfoModule.h
index a2729f16e..20f68ca87 100644
--- a/src/modules/NeighborInfoModule.h
+++ b/src/modules/NeighborInfoModule.h
@@ -65,7 +65,7 @@ class NeighborInfoModule : public ProtobufModule, priva
     }
 
     /* update neighbors with subpacket sniffed from network */
-    void updateNeighbors(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *np);
+    void updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np);
 
     /* update a NeighborInfo packet with our NodeNum as last_sent_by_id */
     void updateLastSentById(meshtastic_MeshPacket *p);
diff --git a/src/modules/PositionModule.cpp b/src/modules/PositionModule.cpp
index 10289b837..cb49f0a8f 100644
--- a/src/modules/PositionModule.cpp
+++ b/src/modules/PositionModule.cpp
@@ -185,7 +185,7 @@ int32_t PositionModule::runOnce()
     } else if (config.position.position_broadcast_smart_enabled) {
         // Only send packets if the channel is less than 25% utilized or we're a tracker.
         if (airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER)) {
-            meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position
+            const meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position
 
             if (hasValidPosition(node2)) {
                 // The minimum distance to travel before we are able to send a new position packet.
diff --git a/src/modules/SerialModule.cpp b/src/modules/SerialModule.cpp
index 4482aae90..16cd3a263 100644
--- a/src/modules/SerialModule.cpp
+++ b/src/modules/SerialModule.cpp
@@ -217,7 +217,7 @@ meshtastic_MeshPacket *SerialModuleRadio::allocReply()
  */
 void SerialModuleRadio::sendPayload(NodeNum dest, bool wantReplies)
 {
-    meshtastic_Channel *ch = (boundChannel != NULL) ? &channels.getByName(boundChannel) : NULL;
+    const meshtastic_Channel *ch = (boundChannel != NULL) ? &channels.getByName(boundChannel) : NULL;
     meshtastic_MeshPacket *p = allocReply();
     p->to = dest;
     if (ch != NULL) {
diff --git a/src/modules/TraceRouteModule.cpp b/src/modules/TraceRouteModule.cpp
index f26c40d2f..bf7eaa0cd 100644
--- a/src/modules/TraceRouteModule.cpp
+++ b/src/modules/TraceRouteModule.cpp
@@ -66,7 +66,7 @@ meshtastic_MeshPacket *TraceRouteModule::allocReply()
 
     // Copy the payload of the current request
     auto req = *currentRequest;
-    auto &p = req.decoded;
+    const auto &p = req.decoded;
     meshtastic_RouteDiscovery scratch;
     meshtastic_RouteDiscovery *updated = NULL;
     memset(&scratch, 0, sizeof(scratch));
diff --git a/src/modules/esp32/StoreForwardModule.cpp b/src/modules/esp32/StoreForwardModule.cpp
index de4d4da3b..6b2c079cc 100644
--- a/src/modules/esp32/StoreForwardModule.cpp
+++ b/src/modules/esp32/StoreForwardModule.cpp
@@ -227,7 +227,7 @@ void StoreForwardModule::sendPayload(NodeNum dest, uint32_t packetHistory_index)
  * @param dest The destination node number.
  * @param payload The message payload to be sent.
  */
-void StoreForwardModule::sendMessage(NodeNum dest, meshtastic_StoreAndForward &payload)
+void StoreForwardModule::sendMessage(NodeNum dest, const meshtastic_StoreAndForward &payload)
 {
     meshtastic_MeshPacket *p = allocDataProtobuf(payload);
 
diff --git a/src/modules/esp32/StoreForwardModule.h b/src/modules/esp32/StoreForwardModule.h
index 23f42e4ae..806f0a836 100644
--- a/src/modules/esp32/StoreForwardModule.h
+++ b/src/modules/esp32/StoreForwardModule.h
@@ -57,7 +57,7 @@ class StoreForwardModule : private concurrency::OSThread, public ProtobufModule<
      * Send our payload into the mesh
      */
     void sendPayload(NodeNum dest = NODENUM_BROADCAST, uint32_t packetHistory_index = 0);
-    void sendMessage(NodeNum dest, meshtastic_StoreAndForward &payload);
+    void sendMessage(NodeNum dest, const meshtastic_StoreAndForward &payload);
     void sendMessage(NodeNum dest, meshtastic_StoreAndForward_RequestResponse rr);
 
     virtual meshtastic_MeshPacket *allocReply() override;
diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp
index 4e5a84477..7a1861756 100644
--- a/src/mqtt/MQTT.cpp
+++ b/src/mqtt/MQTT.cpp
@@ -333,7 +333,7 @@ void MQTT::sendSubscriptions()
 #ifdef HAS_NETWORKING
     size_t numChan = channels.getNumChannels();
     for (size_t i = 0; i < numChan; i++) {
-        auto &ch = channels.getByIndex(i);
+        const auto &ch = channels.getByIndex(i);
         if (ch.settings.downlink_enabled) {
             std::string topic = cryptTopic + channels.getGlobalId(i) + "/#";
             LOG_INFO("Subscribing to %s\n", topic.c_str());
@@ -356,7 +356,7 @@ bool MQTT::wantsLink() const
         // No need for link if no channel needed it
         size_t numChan = channels.getNumChannels();
         for (size_t i = 0; i < numChan; i++) {
-            auto &ch = channels.getByIndex(i);
+            const auto &ch = channels.getByIndex(i);
             if (ch.settings.uplink_enabled || ch.settings.downlink_enabled) {
                 hasChannel = true;
                 break;
diff --git a/suppressions.txt b/suppressions.txt
index e2af9aeef..e65afc0bf 100644
--- a/suppressions.txt
+++ b/suppressions.txt
@@ -28,6 +28,9 @@ useInitializationList
 //unreadVariable:src/graphics/Screen.cpp
 unreadVariable
 
+// I don't want to go back and cast function pointers just to appease a tools insatiable thirst for immutability
+constParameterCallback
+
 redundantInitialization
 
 //cstyleCast:src/mesh/MemoryPool.h:71
@@ -46,4 +49,4 @@ virtualCallInConstructor
 
 passedByValue:*/RedirectablePrint.h
 
-internalAstError:*/CrossPlatformCryptoEngine.cpp
+internalAstError:*/CrossPlatformCryptoEngine.cpp
\ No newline at end of file

From c44986127e39f2267a18a0d3e4bb1618008db5f2 Mon Sep 17 00:00:00 2001
From: Jonathan Bennett 
Date: Sat, 12 Aug 2023 09:29:44 -0500
Subject: [PATCH 14/24] More GPS work (#2711)

Increase GPS buffer on esp32
Check for and flush GPS buffer when overfilled and corrupted.

Co-authored-by: Ben Meadors 
---
 arch/esp32/esp32.ini |  1 +
 src/gps/GPS.cpp      | 10 +++++++++-
 src/gps/GPS.h        |  3 +++
 src/gps/NMEAGPS.cpp  | 10 ++++++++--
 4 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini
index f57ad549d..5853baf76 100644
--- a/arch/esp32/esp32.ini
+++ b/arch/esp32/esp32.ini
@@ -30,6 +30,7 @@ build_flags =
   -DCONFIG_BT_NIMBLE_MAX_CCCDS=20
   -DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=5120
   -DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
+  -DSERIAL_BUFFER_SIZE=4096
   ;-DDEBUG_HEAP
 
 lib_deps =
diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp
index 0e60d149e..85cb046f4 100644
--- a/src/gps/GPS.cpp
+++ b/src/gps/GPS.cpp
@@ -174,7 +174,7 @@ bool GPS::setupGPS()
 
 #ifdef ARCH_ESP32
         // In esp32 framework, setRxBufferSize needs to be initialized before Serial
-        _serial_gps->setRxBufferSize(2048); // the default is 256
+        _serial_gps->setRxBufferSize(SERIAL_BUFFER_SIZE); // the default is 256
 #endif
 
         // if the overrides are not dialled in, set them from the board definitions, if they exist
@@ -834,6 +834,14 @@ void GPS::forceWake(bool on)
     }
 }
 
+// clear the GPS rx buffer as quickly as possible
+void GPS::clearBuffer()
+{
+    int x = _serial_gps->available();
+    while (x--)
+        _serial_gps->read();
+}
+
 /// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
 int GPS::prepareSleep(void *unused)
 {
diff --git a/src/gps/GPS.h b/src/gps/GPS.h
index 847a60016..89f6c491d 100644
--- a/src/gps/GPS.h
+++ b/src/gps/GPS.h
@@ -91,6 +91,9 @@ class GPS : private concurrency::OSThread
     // Some GPS modules (ublock) require factory reset
     virtual bool factoryReset() { return true; }
 
+    // Empty the input buffer as quickly as possible
+    void clearBuffer();
+
   protected:
     /// Do gps chipset specific init, return true for success
     virtual bool setupGPS();
diff --git a/src/gps/NMEAGPS.cpp b/src/gps/NMEAGPS.cpp
index b2cbcfa81..cf08b6be2 100644
--- a/src/gps/NMEAGPS.cpp
+++ b/src/gps/NMEAGPS.cpp
@@ -253,8 +253,14 @@ bool NMEAGPS::hasFlow()
 bool NMEAGPS::whileIdle()
 {
     bool isValid = false;
+#ifdef SERIAL_BUFFER_SIZE
+    if (_serial_gps->available() >= SERIAL_BUFFER_SIZE - 1) {
+        LOG_WARN("GPS Buffer full with %u bytes waiting. Flushing to avoid corruption.\n", _serial_gps->available());
+        clearBuffer();
+    }
+#endif
     // if (_serial_gps->available() > 0)
-    // LOG_DEBUG("GPS Bytes Waiting: %u\n", _serial_gps->available());
+    LOG_DEBUG("GPS Bytes Waiting: %u\n", _serial_gps->available());
     // First consume any chars that have piled up at the receiver
     while (_serial_gps->available() > 0) {
         int c = _serial_gps->read();
@@ -263,4 +269,4 @@ bool NMEAGPS::whileIdle()
     }
 
     return isValid;
-}
+}
\ No newline at end of file

From d29c975e3c9c590e27f07b5658bcb4e40b7b6355 Mon Sep 17 00:00:00 2001
From: Jonathan Bennett 
Date: Sat, 12 Aug 2023 13:51:31 -0500
Subject: [PATCH 15/24] Comment out extra-chatty debug message (#2715)

---
 src/gps/NMEAGPS.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/gps/NMEAGPS.cpp b/src/gps/NMEAGPS.cpp
index cf08b6be2..202185a3b 100644
--- a/src/gps/NMEAGPS.cpp
+++ b/src/gps/NMEAGPS.cpp
@@ -260,7 +260,7 @@ bool NMEAGPS::whileIdle()
     }
 #endif
     // if (_serial_gps->available() > 0)
-    LOG_DEBUG("GPS Bytes Waiting: %u\n", _serial_gps->available());
+    // LOG_DEBUG("GPS Bytes Waiting: %u\n", _serial_gps->available());
     // First consume any chars that have piled up at the receiver
     while (_serial_gps->available() > 0) {
         int c = _serial_gps->read();

From fb5f2e48a565bc8f51c41d98c6127f90fe8e4402 Mon Sep 17 00:00:00 2001
From: Manuel <71137295+mverch67@users.noreply.github.com>
Date: Sun, 13 Aug 2023 02:44:05 +0200
Subject: [PATCH 16/24] fix T-Deck trackball crashes (#2714)

* try-fix: nodenum crash during boot

* Revert "try-fix: nodenum crash during boot"

This reverts commit 632012e197632aafdbd5ef09872622274e00bcc0.

* fix/workaround: trackball interrupt crashes

* trunk fmt

* add OSThread to trackballInterrupt
---
 src/PowerFSM.cpp                     |  2 +-
 src/graphics/Screen.cpp              |  2 +-
 src/input/TrackballInterruptBase.cpp | 65 ++++++++++++++++++----------
 src/input/TrackballInterruptBase.h   | 16 ++++++-
 src/modules/CannedMessageModule.cpp  |  8 ++--
 5 files changed, 62 insertions(+), 31 deletions(-)

diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp
index a873e93c7..827720d1f 100644
--- a/src/PowerFSM.cpp
+++ b/src/PowerFSM.cpp
@@ -177,7 +177,7 @@ static void serialExit()
 
 static void powerEnter()
 {
-    LOG_DEBUG("Enter state: POWER\n");
+    // LOG_DEBUG("Enter state: POWER\n");
     if (!isPowered()) {
         // If we got here, we are in the wrong state - we should be in powered, let that state ahndle things
         LOG_INFO("Loss of power in Powered\n");
diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp
index 53e2ea95f..d4ed6fdb6 100644
--- a/src/graphics/Screen.cpp
+++ b/src/graphics/Screen.cpp
@@ -1901,7 +1901,7 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
 int Screen::handleInputEvent(const InputEvent *event)
 {
     if (showingNormalScreen && moduleFrames.size() == 0) {
-        LOG_DEBUG("Screen::handleInputEvent from %s\n", event->source);
+        // LOG_DEBUG("Screen::handleInputEvent from %s\n", event->source);
         if (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
             showPrevFrame();
         } else if (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
diff --git a/src/input/TrackballInterruptBase.cpp b/src/input/TrackballInterruptBase.cpp
index 649e4b362..71cd130cc 100644
--- a/src/input/TrackballInterruptBase.cpp
+++ b/src/input/TrackballInterruptBase.cpp
@@ -1,10 +1,7 @@
 #include "TrackballInterruptBase.h"
 #include "configuration.h"
 
-TrackballInterruptBase::TrackballInterruptBase(const char *name)
-{
-    this->_originName = name;
-}
+TrackballInterruptBase::TrackballInterruptBase(const char *name) : concurrency::OSThread(name), _originName(name) {}
 
 void TrackballInterruptBase::init(uint8_t pinDown, uint8_t pinUp, uint8_t pinLeft, uint8_t pinRight, uint8_t pinPress,
                                   char eventDown, char eventUp, char eventLeft, char eventRight, char eventPressed,
@@ -35,44 +32,64 @@ void TrackballInterruptBase::init(uint8_t pinDown, uint8_t pinUp, uint8_t pinLef
 
     LOG_DEBUG("Trackball GPIO initialized (%d, %d, %d, %d, %d)\n", this->_pinUp, this->_pinDown, this->_pinLeft, this->_pinRight,
               pinPress);
+
+    this->setInterval(100);
+}
+
+int32_t TrackballInterruptBase::runOnce()
+{
+    InputEvent e;
+    e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
+
+    if (this->action == TB_ACTION_PRESSED) {
+        // LOG_DEBUG("Trackball event Press\n");
+        e.inputEvent = this->_eventPressed;
+    } else if (this->action == TB_ACTION_UP) {
+        // LOG_DEBUG("Trackball event UP\n");
+        e.inputEvent = this->_eventUp;
+    } else if (this->action == TB_ACTION_DOWN) {
+        // LOG_DEBUG("Trackball event DOWN\n");
+        e.inputEvent = this->_eventDown;
+    } else if (this->action == TB_ACTION_LEFT) {
+        // LOG_DEBUG("Trackball event LEFT\n");
+        e.inputEvent = this->_eventLeft;
+    } else if (this->action == TB_ACTION_RIGHT) {
+        // LOG_DEBUG("Trackball event RIGHT\n");
+        e.inputEvent = this->_eventRight;
+    }
+
+    if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
+        e.source = this->_originName;
+        e.kbchar = 0x00;
+        this->notifyObservers(&e);
+    }
+
+    this->action = TB_ACTION_NONE;
+
+    return 100;
 }
 
 void TrackballInterruptBase::intPressHandler()
 {
-    InputEvent e;
-    e.source = this->_originName;
-    e.inputEvent = this->_eventPressed;
-    this->notifyObservers(&e);
+    this->action = TB_ACTION_PRESSED;
 }
 
 void TrackballInterruptBase::intDownHandler()
 {
-    InputEvent e;
-    e.source = this->_originName;
-    e.inputEvent = this->_eventDown;
-    this->notifyObservers(&e);
+    this->action = TB_ACTION_DOWN;
 }
 
 void TrackballInterruptBase::intUpHandler()
 {
-    InputEvent e;
-    e.source = this->_originName;
-    e.inputEvent = this->_eventUp;
-    this->notifyObservers(&e);
+    this->action = TB_ACTION_UP;
 }
 
 void TrackballInterruptBase::intLeftHandler()
 {
-    InputEvent e;
-    e.source = this->_originName;
-    e.inputEvent = this->_eventLeft;
-    this->notifyObservers(&e);
+    this->action = TB_ACTION_LEFT;
 }
 
 void TrackballInterruptBase::intRightHandler()
 {
-    InputEvent e;
-    e.source = this->_originName;
-    e.inputEvent = this->_eventRight;
-    this->notifyObservers(&e);
+    this->action = TB_ACTION_RIGHT;
 }
diff --git a/src/input/TrackballInterruptBase.h b/src/input/TrackballInterruptBase.h
index a82a20cb0..e7fc99f54 100644
--- a/src/input/TrackballInterruptBase.h
+++ b/src/input/TrackballInterruptBase.h
@@ -3,7 +3,7 @@
 #include "InputBroker.h"
 #include "mesh/NodeDB.h"
 
-class TrackballInterruptBase : public Observable
+class TrackballInterruptBase : public Observable, public concurrency::OSThread
 {
   public:
     explicit TrackballInterruptBase(const char *name);
@@ -16,6 +16,20 @@ class TrackballInterruptBase : public Observable
     void intLeftHandler();
     void intRightHandler();
 
+    virtual int32_t runOnce() override;
+
+  protected:
+    enum TrackballInterruptBaseActionType {
+        TB_ACTION_NONE,
+        TB_ACTION_PRESSED,
+        TB_ACTION_UP,
+        TB_ACTION_DOWN,
+        TB_ACTION_LEFT,
+        TB_ACTION_RIGHT
+    };
+
+    volatile TrackballInterruptBaseActionType action = TB_ACTION_NONE;
+
   private:
     uint8_t _pinDown = 0;
     uint8_t _pinUp = 0;
diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp
index 71a9d746c..e1267ba2a 100644
--- a/src/modules/CannedMessageModule.cpp
+++ b/src/modules/CannedMessageModule.cpp
@@ -141,12 +141,12 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
 
     bool validEvent = false;
     if (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP)) {
-        LOG_DEBUG("Canned message event UP\n");
+        // LOG_DEBUG("Canned message event UP\n");
         this->runState = CANNED_MESSAGE_RUN_STATE_ACTION_UP;
         validEvent = true;
     }
     if (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN)) {
-        LOG_DEBUG("Canned message event DOWN\n");
+        // LOG_DEBUG("Canned message event DOWN\n");
         this->runState = CANNED_MESSAGE_RUN_STATE_ACTION_DOWN;
         validEvent = true;
     }
@@ -170,8 +170,8 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
     if ((event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK)) ||
         (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) ||
         (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT))) {
-        LOG_DEBUG("Canned message event (%x)\n", event->kbchar);
-        // tweak for left/right events generated via trackball/touch with empty kbchar
+        // LOG_DEBUG("Canned message event (%x)\n", event->kbchar);
+        //  tweak for left/right events generated via trackball/touch with empty kbchar
         if (!event->kbchar) {
             if (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
                 this->payload = 0xb4;

From a3d2b6166c0bfd2a4e59c844752a419e77dad214 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Sat, 12 Aug 2023 20:49:42 -0500
Subject: [PATCH 17/24] [create-pull-request] automated change (#2716)

Co-authored-by: thebentern 
---
 version.properties | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/version.properties b/version.properties
index 8cc16d822..f26bc2b58 100644
--- a/version.properties
+++ b/version.properties
@@ -1,4 +1,4 @@
 [VERSION]  
 major = 2
 minor = 2
-build = 1
+build = 2

From fcfd83bc89b822c0d2e0c55d52c31d82e58c27f8 Mon Sep 17 00:00:00 2001
From: code8buster <20384924+code8buster@users.noreply.github.com>
Date: Sun, 13 Aug 2023 20:56:49 +0000
Subject: [PATCH 18/24] Remove auto GPS shutoff for fixed position nodes
 (#2720)

---
 src/gps/GPS.cpp | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp
index 85cb046f4..27fe36fe5 100644
--- a/src/gps/GPS.cpp
+++ b/src/gps/GPS.cpp
@@ -805,15 +805,6 @@ int32_t GPS::runOnce()
 
     // If state has changed do a publish
     publishUpdate();
-
-    if (!(fixeddelayCtr >= 20) && config.position.fixed_position && hasValidLocation) {
-        fixeddelayCtr++;
-        // LOG_DEBUG("Our delay counter is %d\n", fixeddelayCtr);
-        if (fixeddelayCtr >= 20) {
-            doGPSpowersave(false);
-            forceWake(false);
-        }
-    }
     // 9600bps is approx 1 byte per msec, so considering our buffer size we never need to wake more often than 200ms
     // if not awake we can run super infrquently (once every 5 secs?) to see if we need to wake.
     return isAwake ? GPS_THREAD_INTERVAL : 5000;

From 18899fd1682c80e557216e6bc60bc138fc1a5dbe Mon Sep 17 00:00:00 2001
From: rcarteraz 
Date: Sun, 13 Aug 2023 21:45:23 -0700
Subject: [PATCH 19/24] Update variant.h (#2719)

remove HAS_GPS 0 so users can add gps

Co-authored-by: Ben Meadors 
---
 variants/t-deck/variant.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/variants/t-deck/variant.h b/variants/t-deck/variant.h
index 9613d882a..c00229ab9 100644
--- a/variants/t-deck/variant.h
+++ b/variants/t-deck/variant.h
@@ -27,7 +27,6 @@
 #define BUTTON_PIN 0
 // #define BUTTON_NEED_PULLUP
 
-#define HAS_GPS 0
 #undef GPS_RX_PIN
 #undef GPS_TX_PIN
 
@@ -86,4 +85,4 @@
 #define SX126X_RESET LORA_RESET
 #define SX126X_E22 // Not really an E22 but TTGO seems to be trying to clone that
 // Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface
-// code)
+// code)
\ No newline at end of file

From 144dfe98059875eeabc2204313598a850ca08a3f Mon Sep 17 00:00:00 2001
From: Ben Meadors 
Date: Mon, 14 Aug 2023 19:00:51 -0500
Subject: [PATCH 20/24] Initial Detection sensor module feature (#2722)

* WIP

* Updates

* Doh!

* Move it out of the macro guard so portduino can build

* Changes from feedback
---
 protobufs                                     |  2 +-
 src/mesh/NodeDB.cpp                           |  5 +
 src/mesh/PhoneAPI.cpp                         |  4 +
 src/mesh/generated/meshtastic/admin.pb.h      |  8 +-
 src/mesh/generated/meshtastic/config.pb.h     |  2 +-
 src/mesh/generated/meshtastic/deviceonly.pb.h |  2 +-
 src/mesh/generated/meshtastic/localonly.pb.h  | 20 +++-
 src/mesh/generated/meshtastic/mesh.pb.h       |  2 +-
 .../generated/meshtastic/module_config.pb.c   |  3 +
 .../generated/meshtastic/module_config.pb.h   | 60 ++++++++++-
 src/modules/AdminModule.cpp                   | 10 ++
 src/modules/DetectionSensorModule.cpp         | 99 +++++++++++++++++++
 src/modules/DetectionSensorModule.h           | 23 +++++
 src/modules/Modules.cpp                       |  2 +
 14 files changed, 230 insertions(+), 12 deletions(-)
 create mode 100644 src/modules/DetectionSensorModule.cpp
 create mode 100644 src/modules/DetectionSensorModule.h

diff --git a/protobufs b/protobufs
index 6320d6795..dc28ae3d1 160000
--- a/protobufs
+++ b/protobufs
@@ -1 +1 @@
-Subproject commit 6320d6795e5462da38ab0bdc3769163a0fac37c6
+Subproject commit dc28ae3d128b76707c0b87b6f3b2514c7f8514bd
diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp
index 924d98698..196874d48 100644
--- a/src/mesh/NodeDB.cpp
+++ b/src/mesh/NodeDB.cpp
@@ -248,6 +248,11 @@ void NodeDB::installDefaultModuleConfig()
     moduleConfig.has_neighbor_info = true;
     moduleConfig.neighbor_info.enabled = false;
 
+    moduleConfig.has_detection_sensor = true;
+    moduleConfig.detection_sensor.enabled = false;
+    moduleConfig.detection_sensor.detection_triggered_high = true;
+    moduleConfig.detection_sensor.minimum_broadcast_secs = 45;
+
     initModuleConfigIntervals();
 }
 
diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp
index cd230cb1c..c91f2e815 100644
--- a/src/mesh/PhoneAPI.cpp
+++ b/src/mesh/PhoneAPI.cpp
@@ -283,6 +283,10 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
             fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_neighbor_info_tag;
             fromRadioScratch.moduleConfig.payload_variant.neighbor_info = moduleConfig.neighbor_info;
             break;
+        case meshtastic_ModuleConfig_detection_sensor_tag:
+            fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_detection_sensor_tag;
+            fromRadioScratch.moduleConfig.payload_variant.detection_sensor = moduleConfig.detection_sensor;
+            break;
         default:
             LOG_ERROR("Unknown module config type %d\n", config_state);
         }
diff --git a/src/mesh/generated/meshtastic/admin.pb.h b/src/mesh/generated/meshtastic/admin.pb.h
index 89e1fde0c..38248d94a 100644
--- a/src/mesh/generated/meshtastic/admin.pb.h
+++ b/src/mesh/generated/meshtastic/admin.pb.h
@@ -57,7 +57,9 @@ typedef enum _meshtastic_AdminMessage_ModuleConfigType {
     /* TODO: REPLACE */
     meshtastic_AdminMessage_ModuleConfigType_NEIGHBORINFO_CONFIG = 9,
     /* TODO: REPLACE */
-    meshtastic_AdminMessage_ModuleConfigType_AMBIENTLIGHTING_CONFIG = 10
+    meshtastic_AdminMessage_ModuleConfigType_AMBIENTLIGHTING_CONFIG = 10,
+    /* TODO: REPLACE */
+    meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG = 11
 } meshtastic_AdminMessage_ModuleConfigType;
 
 /* Struct definitions */
@@ -176,8 +178,8 @@ extern "C" {
 #define _meshtastic_AdminMessage_ConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ConfigType)(meshtastic_AdminMessage_ConfigType_BLUETOOTH_CONFIG+1))
 
 #define _meshtastic_AdminMessage_ModuleConfigType_MIN meshtastic_AdminMessage_ModuleConfigType_MQTT_CONFIG
-#define _meshtastic_AdminMessage_ModuleConfigType_MAX meshtastic_AdminMessage_ModuleConfigType_AMBIENTLIGHTING_CONFIG
-#define _meshtastic_AdminMessage_ModuleConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ModuleConfigType)(meshtastic_AdminMessage_ModuleConfigType_AMBIENTLIGHTING_CONFIG+1))
+#define _meshtastic_AdminMessage_ModuleConfigType_MAX meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG
+#define _meshtastic_AdminMessage_ModuleConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ModuleConfigType)(meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG+1))
 
 #define meshtastic_AdminMessage_payload_variant_get_config_request_ENUMTYPE meshtastic_AdminMessage_ConfigType
 #define meshtastic_AdminMessage_payload_variant_get_module_config_request_ENUMTYPE meshtastic_AdminMessage_ModuleConfigType
diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h
index a02b41a76..ef9d09a19 100644
--- a/src/mesh/generated/meshtastic/config.pb.h
+++ b/src/mesh/generated/meshtastic/config.pb.h
@@ -269,7 +269,7 @@ typedef struct _meshtastic_Config_PositionConfig {
     uint32_t tx_gpio;
     /* The minimum distance in meters traveled (since the last send) before we can send a position to the mesh if position_broadcast_smart_enabled */
     uint32_t broadcast_smart_minimum_distance;
-    /* The minumum number of seconds (since the last send) before we can send a position to the mesh if position_broadcast_smart_enabled */
+    /* The minimum number of seconds (since the last send) before we can send a position to the mesh if position_broadcast_smart_enabled */
     uint32_t broadcast_smart_minimum_interval_secs;
 } meshtastic_Config_PositionConfig;
 
diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h
index 998b02bcc..143bd4482 100644
--- a/src/mesh/generated/meshtastic/deviceonly.pb.h
+++ b/src/mesh/generated/meshtastic/deviceonly.pb.h
@@ -316,7 +316,7 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg;
 #define meshtastic_DeviceState_size              16854
 #define meshtastic_NodeInfoLite_size             151
 #define meshtastic_NodeRemoteHardwarePin_size    29
-#define meshtastic_OEMStore_size                 3148
+#define meshtastic_OEMStore_size                 3210
 #define meshtastic_PositionLite_size             28
 
 #ifdef __cplusplus
diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h
index 4c27e0b67..471074948 100644
--- a/src/mesh/generated/meshtastic/localonly.pb.h
+++ b/src/mesh/generated/meshtastic/localonly.pb.h
@@ -75,6 +75,12 @@ typedef struct _meshtastic_LocalModuleConfig {
     /* The part of the config that is specific to the Neighbor Info module */
     bool has_neighbor_info;
     meshtastic_ModuleConfig_NeighborInfoConfig neighbor_info;
+    /* The part of the config that is specific to the Ambient Lighting module */
+    bool has_ambient_lighting;
+    meshtastic_ModuleConfig_AmbientLightingConfig ambient_lighting;
+    /* The part of the config that is specific to the Detection Sensor module */
+    bool has_detection_sensor;
+    meshtastic_ModuleConfig_DetectionSensorConfig detection_sensor;
 } meshtastic_LocalModuleConfig;
 
 
@@ -84,9 +90,9 @@ extern "C" {
 
 /* Initializer values for message structs */
 #define meshtastic_LocalConfig_init_default      {false, meshtastic_Config_DeviceConfig_init_default, false, meshtastic_Config_PositionConfig_init_default, false, meshtastic_Config_PowerConfig_init_default, false, meshtastic_Config_NetworkConfig_init_default, false, meshtastic_Config_DisplayConfig_init_default, false, meshtastic_Config_LoRaConfig_init_default, false, meshtastic_Config_BluetoothConfig_init_default, 0}
-#define meshtastic_LocalModuleConfig_init_default {false, meshtastic_ModuleConfig_MQTTConfig_init_default, false, meshtastic_ModuleConfig_SerialConfig_init_default, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_default, false, meshtastic_ModuleConfig_StoreForwardConfig_init_default, false, meshtastic_ModuleConfig_RangeTestConfig_init_default, false, meshtastic_ModuleConfig_TelemetryConfig_init_default, false, meshtastic_ModuleConfig_CannedMessageConfig_init_default, 0, false, meshtastic_ModuleConfig_AudioConfig_init_default, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_default, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_default}
+#define meshtastic_LocalModuleConfig_init_default {false, meshtastic_ModuleConfig_MQTTConfig_init_default, false, meshtastic_ModuleConfig_SerialConfig_init_default, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_default, false, meshtastic_ModuleConfig_StoreForwardConfig_init_default, false, meshtastic_ModuleConfig_RangeTestConfig_init_default, false, meshtastic_ModuleConfig_TelemetryConfig_init_default, false, meshtastic_ModuleConfig_CannedMessageConfig_init_default, 0, false, meshtastic_ModuleConfig_AudioConfig_init_default, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_default, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_default, false, meshtastic_ModuleConfig_AmbientLightingConfig_init_default, false, meshtastic_ModuleConfig_DetectionSensorConfig_init_default}
 #define meshtastic_LocalConfig_init_zero         {false, meshtastic_Config_DeviceConfig_init_zero, false, meshtastic_Config_PositionConfig_init_zero, false, meshtastic_Config_PowerConfig_init_zero, false, meshtastic_Config_NetworkConfig_init_zero, false, meshtastic_Config_DisplayConfig_init_zero, false, meshtastic_Config_LoRaConfig_init_zero, false, meshtastic_Config_BluetoothConfig_init_zero, 0}
-#define meshtastic_LocalModuleConfig_init_zero   {false, meshtastic_ModuleConfig_MQTTConfig_init_zero, false, meshtastic_ModuleConfig_SerialConfig_init_zero, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero, false, meshtastic_ModuleConfig_StoreForwardConfig_init_zero, false, meshtastic_ModuleConfig_RangeTestConfig_init_zero, false, meshtastic_ModuleConfig_TelemetryConfig_init_zero, false, meshtastic_ModuleConfig_CannedMessageConfig_init_zero, 0, false, meshtastic_ModuleConfig_AudioConfig_init_zero, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_zero}
+#define meshtastic_LocalModuleConfig_init_zero   {false, meshtastic_ModuleConfig_MQTTConfig_init_zero, false, meshtastic_ModuleConfig_SerialConfig_init_zero, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero, false, meshtastic_ModuleConfig_StoreForwardConfig_init_zero, false, meshtastic_ModuleConfig_RangeTestConfig_init_zero, false, meshtastic_ModuleConfig_TelemetryConfig_init_zero, false, meshtastic_ModuleConfig_CannedMessageConfig_init_zero, 0, false, meshtastic_ModuleConfig_AudioConfig_init_zero, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_zero, false, meshtastic_ModuleConfig_AmbientLightingConfig_init_zero, false, meshtastic_ModuleConfig_DetectionSensorConfig_init_zero}
 
 /* Field tags (for use in manual encoding/decoding) */
 #define meshtastic_LocalConfig_device_tag        1
@@ -108,6 +114,8 @@ extern "C" {
 #define meshtastic_LocalModuleConfig_audio_tag   9
 #define meshtastic_LocalModuleConfig_remote_hardware_tag 10
 #define meshtastic_LocalModuleConfig_neighbor_info_tag 11
+#define meshtastic_LocalModuleConfig_ambient_lighting_tag 12
+#define meshtastic_LocalModuleConfig_detection_sensor_tag 13
 
 /* Struct field encoding specification for nanopb */
 #define meshtastic_LocalConfig_FIELDLIST(X, a) \
@@ -140,7 +148,9 @@ X(a, STATIC,   OPTIONAL, MESSAGE,  canned_message,    7) \
 X(a, STATIC,   SINGULAR, UINT32,   version,           8) \
 X(a, STATIC,   OPTIONAL, MESSAGE,  audio,             9) \
 X(a, STATIC,   OPTIONAL, MESSAGE,  remote_hardware,  10) \
-X(a, STATIC,   OPTIONAL, MESSAGE,  neighbor_info,    11)
+X(a, STATIC,   OPTIONAL, MESSAGE,  neighbor_info,    11) \
+X(a, STATIC,   OPTIONAL, MESSAGE,  ambient_lighting,  12) \
+X(a, STATIC,   OPTIONAL, MESSAGE,  detection_sensor,  13)
 #define meshtastic_LocalModuleConfig_CALLBACK NULL
 #define meshtastic_LocalModuleConfig_DEFAULT NULL
 #define meshtastic_LocalModuleConfig_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig
@@ -153,6 +163,8 @@ X(a, STATIC,   OPTIONAL, MESSAGE,  neighbor_info,    11)
 #define meshtastic_LocalModuleConfig_audio_MSGTYPE meshtastic_ModuleConfig_AudioConfig
 #define meshtastic_LocalModuleConfig_remote_hardware_MSGTYPE meshtastic_ModuleConfig_RemoteHardwareConfig
 #define meshtastic_LocalModuleConfig_neighbor_info_MSGTYPE meshtastic_ModuleConfig_NeighborInfoConfig
+#define meshtastic_LocalModuleConfig_ambient_lighting_MSGTYPE meshtastic_ModuleConfig_AmbientLightingConfig
+#define meshtastic_LocalModuleConfig_detection_sensor_MSGTYPE meshtastic_ModuleConfig_DetectionSensorConfig
 
 extern const pb_msgdesc_t meshtastic_LocalConfig_msg;
 extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
@@ -163,7 +175,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
 
 /* Maximum encoded size of messages (where known) */
 #define meshtastic_LocalConfig_size              455
-#define meshtastic_LocalModuleConfig_size        547
+#define meshtastic_LocalModuleConfig_size        609
 
 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h
index 060c18fe1..f319c58b9 100644
--- a/src/mesh/generated/meshtastic/mesh.pb.h
+++ b/src/mesh/generated/meshtastic/mesh.pb.h
@@ -153,7 +153,7 @@ typedef enum _meshtastic_CriticalErrorCode {
     /* Radio transmit hardware failure. We sent data to the radio chip, but it didn't
  reply with an interrupt. */
     meshtastic_CriticalErrorCode_TRANSMIT_FAILED = 8,
-    /* We detected that the main CPU voltage dropped below the minumum acceptable value */
+    /* We detected that the main CPU voltage dropped below the minimum acceptable value */
     meshtastic_CriticalErrorCode_BROWNOUT = 9,
     /* Selftest of SX1262 radio chip failed */
     meshtastic_CriticalErrorCode_SX1262_FAILURE = 10,
diff --git a/src/mesh/generated/meshtastic/module_config.pb.c b/src/mesh/generated/meshtastic/module_config.pb.c
index 86614d18c..7318d34f7 100644
--- a/src/mesh/generated/meshtastic/module_config.pb.c
+++ b/src/mesh/generated/meshtastic/module_config.pb.c
@@ -18,6 +18,9 @@ PB_BIND(meshtastic_ModuleConfig_RemoteHardwareConfig, meshtastic_ModuleConfig_Re
 PB_BIND(meshtastic_ModuleConfig_NeighborInfoConfig, meshtastic_ModuleConfig_NeighborInfoConfig, AUTO)
 
 
+PB_BIND(meshtastic_ModuleConfig_DetectionSensorConfig, meshtastic_ModuleConfig_DetectionSensorConfig, AUTO)
+
+
 PB_BIND(meshtastic_ModuleConfig_AudioConfig, meshtastic_ModuleConfig_AudioConfig, AUTO)
 
 
diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h
index 43b330b04..828a44cc7 100644
--- a/src/mesh/generated/meshtastic/module_config.pb.h
+++ b/src/mesh/generated/meshtastic/module_config.pb.h
@@ -125,6 +125,33 @@ typedef struct _meshtastic_ModuleConfig_NeighborInfoConfig {
     uint32_t update_interval;
 } meshtastic_ModuleConfig_NeighborInfoConfig;
 
+/* Detection Sensor Module Config */
+typedef struct _meshtastic_ModuleConfig_DetectionSensorConfig {
+    /* Whether the Module is enabled */
+    bool enabled;
+    /* Interval in seconds of how often we can send a message to the mesh when a state change is detected */
+    uint32_t minimum_broadcast_secs;
+    /* Interval in seconds of how often we should send a message to the mesh with the current state regardless of changes
+ When set to 0, only state changes will be broadcasted
+ Works as a sort of status heartbeat for peace of mind */
+    uint32_t state_broadcast_secs;
+    /* Send ASCII bell with alert message
+ Useful for triggering ext. notification on bell */
+    bool send_bell;
+    /* Friendly name used to format message sent to mesh
+ Example: A name "Motion" would result in a message "Motion detected"
+ Maximum length of 20 characters */
+    char name[20];
+    /* GPIO pin to monitor for state changes */
+    uint8_t monitor_pin;
+    /* Whether or not the GPIO pin state detection is triggered on HIGH (1)
+ Otherwise LOW (0) */
+    bool detection_triggered_high;
+    /* Whether or not use INPUT_PULLUP mode for GPIO pin
+ Only applicable if the board uses pull-up resistors on the pin */
+    bool use_pullup;
+} meshtastic_ModuleConfig_DetectionSensorConfig;
+
 /* Audio Config for codec2 voice */
 typedef struct _meshtastic_ModuleConfig_AudioConfig {
     /* Whether Audio is enabled */
@@ -342,6 +369,8 @@ typedef struct _meshtastic_ModuleConfig {
         meshtastic_ModuleConfig_NeighborInfoConfig neighbor_info;
         /* TODO: REPLACE */
         meshtastic_ModuleConfig_AmbientLightingConfig ambient_lighting;
+        /* TODO: REPLACE */
+        meshtastic_ModuleConfig_DetectionSensorConfig detection_sensor;
     } payload_variant;
 } meshtastic_ModuleConfig;
 
@@ -375,6 +404,7 @@ extern "C" {
 
 
 
+
 #define meshtastic_ModuleConfig_AudioConfig_bitrate_ENUMTYPE meshtastic_ModuleConfig_AudioConfig_Audio_Baud
 
 #define meshtastic_ModuleConfig_SerialConfig_baud_ENUMTYPE meshtastic_ModuleConfig_SerialConfig_Serial_Baud
@@ -397,6 +427,7 @@ extern "C" {
 #define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0, "", 0}
 #define meshtastic_ModuleConfig_RemoteHardwareConfig_init_default {0, 0, 0, {meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default}}
 #define meshtastic_ModuleConfig_NeighborInfoConfig_init_default {0, 0}
+#define meshtastic_ModuleConfig_DetectionSensorConfig_init_default {0, 0, 0, 0, "", 0, 0, 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, 0}
 #define meshtastic_ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
@@ -410,6 +441,7 @@ extern "C" {
 #define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0, "", 0}
 #define meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero {0, 0, 0, {meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero}}
 #define meshtastic_ModuleConfig_NeighborInfoConfig_init_zero {0, 0}
+#define meshtastic_ModuleConfig_DetectionSensorConfig_init_zero {0, 0, 0, 0, "", 0, 0, 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, 0}
 #define meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
@@ -432,6 +464,14 @@ extern "C" {
 #define meshtastic_ModuleConfig_MQTTConfig_proxy_to_client_enabled_tag 9
 #define meshtastic_ModuleConfig_NeighborInfoConfig_enabled_tag 1
 #define meshtastic_ModuleConfig_NeighborInfoConfig_update_interval_tag 2
+#define meshtastic_ModuleConfig_DetectionSensorConfig_enabled_tag 1
+#define meshtastic_ModuleConfig_DetectionSensorConfig_minimum_broadcast_secs_tag 2
+#define meshtastic_ModuleConfig_DetectionSensorConfig_state_broadcast_secs_tag 3
+#define meshtastic_ModuleConfig_DetectionSensorConfig_send_bell_tag 4
+#define meshtastic_ModuleConfig_DetectionSensorConfig_name_tag 5
+#define meshtastic_ModuleConfig_DetectionSensorConfig_monitor_pin_tag 6
+#define meshtastic_ModuleConfig_DetectionSensorConfig_detection_triggered_high_tag 7
+#define meshtastic_ModuleConfig_DetectionSensorConfig_use_pullup_tag 8
 #define meshtastic_ModuleConfig_AudioConfig_codec2_enabled_tag 1
 #define meshtastic_ModuleConfig_AudioConfig_ptt_pin_tag 2
 #define meshtastic_ModuleConfig_AudioConfig_bitrate_tag 3
@@ -509,6 +549,7 @@ extern "C" {
 #define meshtastic_ModuleConfig_remote_hardware_tag 9
 #define meshtastic_ModuleConfig_neighbor_info_tag 10
 #define meshtastic_ModuleConfig_ambient_lighting_tag 11
+#define meshtastic_ModuleConfig_detection_sensor_tag 12
 
 /* Struct field encoding specification for nanopb */
 #define meshtastic_ModuleConfig_FIELDLIST(X, a) \
@@ -522,7 +563,8 @@ X(a, STATIC,   ONEOF,    MESSAGE,  (payload_variant,canned_message,payload_varia
 X(a, STATIC,   ONEOF,    MESSAGE,  (payload_variant,audio,payload_variant.audio),   8) \
 X(a, STATIC,   ONEOF,    MESSAGE,  (payload_variant,remote_hardware,payload_variant.remote_hardware),   9) \
 X(a, STATIC,   ONEOF,    MESSAGE,  (payload_variant,neighbor_info,payload_variant.neighbor_info),  10) \
-X(a, STATIC,   ONEOF,    MESSAGE,  (payload_variant,ambient_lighting,payload_variant.ambient_lighting),  11)
+X(a, STATIC,   ONEOF,    MESSAGE,  (payload_variant,ambient_lighting,payload_variant.ambient_lighting),  11) \
+X(a, STATIC,   ONEOF,    MESSAGE,  (payload_variant,detection_sensor,payload_variant.detection_sensor),  12)
 #define meshtastic_ModuleConfig_CALLBACK NULL
 #define meshtastic_ModuleConfig_DEFAULT NULL
 #define meshtastic_ModuleConfig_payload_variant_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig
@@ -536,6 +578,7 @@ X(a, STATIC,   ONEOF,    MESSAGE,  (payload_variant,ambient_lighting,payload_var
 #define meshtastic_ModuleConfig_payload_variant_remote_hardware_MSGTYPE meshtastic_ModuleConfig_RemoteHardwareConfig
 #define meshtastic_ModuleConfig_payload_variant_neighbor_info_MSGTYPE meshtastic_ModuleConfig_NeighborInfoConfig
 #define meshtastic_ModuleConfig_payload_variant_ambient_lighting_MSGTYPE meshtastic_ModuleConfig_AmbientLightingConfig
+#define meshtastic_ModuleConfig_payload_variant_detection_sensor_MSGTYPE meshtastic_ModuleConfig_DetectionSensorConfig
 
 #define meshtastic_ModuleConfig_MQTTConfig_FIELDLIST(X, a) \
 X(a, STATIC,   SINGULAR, BOOL,     enabled,           1) \
@@ -564,6 +607,18 @@ X(a, STATIC,   SINGULAR, UINT32,   update_interval,   2)
 #define meshtastic_ModuleConfig_NeighborInfoConfig_CALLBACK NULL
 #define meshtastic_ModuleConfig_NeighborInfoConfig_DEFAULT NULL
 
+#define meshtastic_ModuleConfig_DetectionSensorConfig_FIELDLIST(X, a) \
+X(a, STATIC,   SINGULAR, BOOL,     enabled,           1) \
+X(a, STATIC,   SINGULAR, UINT32,   minimum_broadcast_secs,   2) \
+X(a, STATIC,   SINGULAR, UINT32,   state_broadcast_secs,   3) \
+X(a, STATIC,   SINGULAR, BOOL,     send_bell,         4) \
+X(a, STATIC,   SINGULAR, STRING,   name,              5) \
+X(a, STATIC,   SINGULAR, UINT32,   monitor_pin,       6) \
+X(a, STATIC,   SINGULAR, BOOL,     detection_triggered_high,   7) \
+X(a, STATIC,   SINGULAR, BOOL,     use_pullup,        8)
+#define meshtastic_ModuleConfig_DetectionSensorConfig_CALLBACK NULL
+#define meshtastic_ModuleConfig_DetectionSensorConfig_DEFAULT NULL
+
 #define meshtastic_ModuleConfig_AudioConfig_FIELDLIST(X, a) \
 X(a, STATIC,   SINGULAR, BOOL,     codec2_enabled,    1) \
 X(a, STATIC,   SINGULAR, UINT32,   ptt_pin,           2) \
@@ -667,6 +722,7 @@ extern const pb_msgdesc_t meshtastic_ModuleConfig_msg;
 extern const pb_msgdesc_t meshtastic_ModuleConfig_MQTTConfig_msg;
 extern const pb_msgdesc_t meshtastic_ModuleConfig_RemoteHardwareConfig_msg;
 extern const pb_msgdesc_t meshtastic_ModuleConfig_NeighborInfoConfig_msg;
+extern const pb_msgdesc_t meshtastic_ModuleConfig_DetectionSensorConfig_msg;
 extern const pb_msgdesc_t meshtastic_ModuleConfig_AudioConfig_msg;
 extern const pb_msgdesc_t meshtastic_ModuleConfig_SerialConfig_msg;
 extern const pb_msgdesc_t meshtastic_ModuleConfig_ExternalNotificationConfig_msg;
@@ -682,6 +738,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
 #define meshtastic_ModuleConfig_MQTTConfig_fields &meshtastic_ModuleConfig_MQTTConfig_msg
 #define meshtastic_ModuleConfig_RemoteHardwareConfig_fields &meshtastic_ModuleConfig_RemoteHardwareConfig_msg
 #define meshtastic_ModuleConfig_NeighborInfoConfig_fields &meshtastic_ModuleConfig_NeighborInfoConfig_msg
+#define meshtastic_ModuleConfig_DetectionSensorConfig_fields &meshtastic_ModuleConfig_DetectionSensorConfig_msg
 #define meshtastic_ModuleConfig_AudioConfig_fields &meshtastic_ModuleConfig_AudioConfig_msg
 #define meshtastic_ModuleConfig_SerialConfig_fields &meshtastic_ModuleConfig_SerialConfig_msg
 #define meshtastic_ModuleConfig_ExternalNotificationConfig_fields &meshtastic_ModuleConfig_ExternalNotificationConfig_msg
@@ -696,6 +753,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
 #define meshtastic_ModuleConfig_AmbientLightingConfig_size 14
 #define meshtastic_ModuleConfig_AudioConfig_size 19
 #define meshtastic_ModuleConfig_CannedMessageConfig_size 49
+#define meshtastic_ModuleConfig_DetectionSensorConfig_size 44
 #define meshtastic_ModuleConfig_ExternalNotificationConfig_size 40
 #define meshtastic_ModuleConfig_MQTTConfig_size  222
 #define meshtastic_ModuleConfig_NeighborInfoConfig_size 8
diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp
index 283375b23..27b539f38 100644
--- a/src/modules/AdminModule.cpp
+++ b/src/modules/AdminModule.cpp
@@ -373,6 +373,11 @@ void AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
         moduleConfig.has_neighbor_info = true;
         moduleConfig.neighbor_info = c.payload_variant.neighbor_info;
         break;
+    case meshtastic_ModuleConfig_detection_sensor_tag:
+        LOG_INFO("Setting module config: Detection Sensor\n");
+        moduleConfig.has_detection_sensor = true;
+        moduleConfig.detection_sensor = c.payload_variant.detection_sensor;
+        break;
     }
 
     saveChanges(SEGMENT_MODULECONFIG);
@@ -513,6 +518,11 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
             res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_neighbor_info_tag;
             res.get_module_config_response.payload_variant.neighbor_info = moduleConfig.neighbor_info;
             break;
+        case meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG:
+            LOG_INFO("Getting module config: Detection Sensor\n");
+            res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_detection_sensor_tag;
+            res.get_module_config_response.payload_variant.detection_sensor = moduleConfig.detection_sensor;
+            break;
         }
 
         // NOTE: The phone app needs to know the ls_secsvalue so it can properly expect sleep behavior.
diff --git a/src/modules/DetectionSensorModule.cpp b/src/modules/DetectionSensorModule.cpp
new file mode 100644
index 000000000..8050c209e
--- /dev/null
+++ b/src/modules/DetectionSensorModule.cpp
@@ -0,0 +1,99 @@
+#include "DetectionSensorModule.h"
+#include "MeshService.h"
+#include "NodeDB.h"
+#include "PowerFSM.h"
+#include "configuration.h"
+#include "main.h"
+
+DetectionSensorModule *detectionSensorModule;
+
+#define GPIO_POLLING_INTERVAL 100
+#define DELAYED_INTERVAL 1000
+
+int32_t DetectionSensorModule::runOnce()
+{
+    /*
+        Uncomment the preferences below if you want to use the module
+        without having to configure it from the PythonAPI or WebUI.
+    */
+    // moduleConfig.detection_sensor.enabled = true;
+    // moduleConfig.detection_sensor.monitor_pin = 10; // WisBlock PIR IO6
+    // moduleConfig.detection_sensor.minimum_broadcast_secs = 60;
+    // moduleConfig.detection_sensor.state_broadcast_secs = 120;
+    // moduleConfig.detection_sensor.detection_triggered_high = false;
+    // strcpy(moduleConfig.detection_sensor.name, "Motion");
+
+    if (moduleConfig.detection_sensor.enabled == false)
+        return disable();
+
+    if (firstTime) {
+        // This is the first time the OSThread library has called this function, so do some setup
+        firstTime = false;
+        if (moduleConfig.detection_sensor.monitor_pin > 0) {
+            pinMode(moduleConfig.detection_sensor.monitor_pin, moduleConfig.detection_sensor.use_pullup ? INPUT_PULLUP : INPUT);
+        } else {
+            LOG_WARN("Detection Sensor Module: Set to enabled but no monitor pin is set. Disabling module...\n");
+            return disable();
+        }
+        LOG_INFO("Detection Sensor Module: Initializing\n");
+
+        return DELAYED_INTERVAL;
+    }
+
+    if ((millis() - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.detection_sensor.minimum_broadcast_secs) &&
+        hasDetectionEvent()) {
+        sendDetectionMessage();
+        return DELAYED_INTERVAL;
+    }
+    // Even if we haven't detected an event, broadcast our current state to the mesh on the scheduled interval as a sort
+    // of heartbeat. We only do this if the minimum broadcast interval is greater than zero, otherwise we'll only broadcast state
+    // change detections.
+    else if (moduleConfig.detection_sensor.state_broadcast_secs > 0 &&
+             (millis() - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.detection_sensor.state_broadcast_secs)) {
+        sendCurrentStateMessage();
+        return DELAYED_INTERVAL;
+    }
+    return GPIO_POLLING_INTERVAL;
+}
+
+void DetectionSensorModule::sendDetectionMessage()
+{
+    LOG_DEBUG("Detected event observed. Sending message\n");
+    char *message = new char[40];
+    sprintf(message, "%s detected", moduleConfig.detection_sensor.name);
+    meshtastic_MeshPacket *p = allocDataPacket();
+    p->want_ack = false;
+    p->decoded.payload.size = strlen(message);
+    memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size);
+    if (moduleConfig.detection_sensor.send_bell && p->decoded.payload.size < meshtastic_Constants_DATA_PAYLOAD_LEN) {
+        p->decoded.payload.bytes[p->decoded.payload.size] = 7;        // Bell character
+        p->decoded.payload.bytes[p->decoded.payload.size + 1] = '\0'; // Bell character
+        p->decoded.payload.size++;
+    }
+    LOG_INFO("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
+    lastSentToMesh = millis();
+    service.sendToMesh(p);
+    delete[] message;
+}
+
+void DetectionSensorModule::sendCurrentStateMessage()
+{
+    char *message = new char[40];
+    sprintf(message, "%s state: %i", moduleConfig.detection_sensor.name, hasDetectionEvent());
+
+    meshtastic_MeshPacket *p = allocDataPacket();
+    p->want_ack = false;
+    p->decoded.payload.size = strlen(message);
+    memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size);
+    LOG_INFO("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
+    lastSentToMesh = millis();
+    service.sendToMesh(p);
+    delete[] message;
+}
+
+bool DetectionSensorModule::hasDetectionEvent()
+{
+    bool currentState = digitalRead(moduleConfig.detection_sensor.monitor_pin);
+    // LOG_DEBUG("Detection Sensor Module: Current state: %i\n", currentState);
+    return moduleConfig.detection_sensor.detection_triggered_high ? currentState : !currentState;
+}
\ No newline at end of file
diff --git a/src/modules/DetectionSensorModule.h b/src/modules/DetectionSensorModule.h
new file mode 100644
index 000000000..bcc0b9419
--- /dev/null
+++ b/src/modules/DetectionSensorModule.h
@@ -0,0 +1,23 @@
+#pragma once
+#include "SinglePortModule.h"
+
+class DetectionSensorModule : public SinglePortModule, private concurrency::OSThread
+{
+  public:
+    DetectionSensorModule()
+        : SinglePortModule("detection", meshtastic_PortNum_TEXT_MESSAGE_APP), OSThread("DetectionSensorModule")
+    {
+    }
+
+  protected:
+    virtual int32_t runOnce() override;
+
+  private:
+    bool firstTime = true;
+    uint32_t lastSentToMesh = 0;
+    void sendDetectionMessage();
+    void sendCurrentStateMessage();
+    bool hasDetectionEvent();
+};
+
+extern DetectionSensorModule *detectionSensorModule;
\ No newline at end of file
diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp
index 9c216ff72..bcb33c640 100644
--- a/src/modules/Modules.cpp
+++ b/src/modules/Modules.cpp
@@ -7,6 +7,7 @@
 #include "input/kbMatrixImpl.h"
 #include "modules/AdminModule.h"
 #include "modules/CannedMessageModule.h"
+#include "modules/DetectionSensorModule.h"
 #include "modules/NeighborInfoModule.h"
 #include "modules/NodeInfoModule.h"
 #include "modules/PositionModule.h"
@@ -50,6 +51,7 @@ void setupModules()
         textMessageModule = new TextMessageModule();
         traceRouteModule = new TraceRouteModule();
         neighborInfoModule = new NeighborInfoModule();
+        detectionSensorModule = new DetectionSensorModule();
 
         // Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance
         // to a global variable.

From 03fe4c629ae17483617d31848f3d59d602f655e1 Mon Sep 17 00:00:00 2001
From: Ben Meadors 
Date: Tue, 15 Aug 2023 12:23:07 -0500
Subject: [PATCH 21/24] Dection Sensor module duty cycle interval optimization
 (#2723)

* WIP

* Updates

* Move it out of the macro guard so portduino can build

* Changes from feedback

* Use minimum_broadcast_secs as interval if we just broadcasted to avoid wasting cpu cycles

* Fmt

* Merge conflict resolution boogered me up

* Missed a spot
---
 src/modules/DetectionSensorModule.cpp | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/modules/DetectionSensorModule.cpp b/src/modules/DetectionSensorModule.cpp
index 8050c209e..c6f71eb56 100644
--- a/src/modules/DetectionSensorModule.cpp
+++ b/src/modules/DetectionSensorModule.cpp
@@ -18,9 +18,10 @@ int32_t DetectionSensorModule::runOnce()
     */
     // moduleConfig.detection_sensor.enabled = true;
     // moduleConfig.detection_sensor.monitor_pin = 10; // WisBlock PIR IO6
-    // moduleConfig.detection_sensor.minimum_broadcast_secs = 60;
+    // moduleConfig.detection_sensor.monitor_pin = 21; // WisBlock RAK12013 Radar IO6
+    // moduleConfig.detection_sensor.minimum_broadcast_secs = 30;
     // moduleConfig.detection_sensor.state_broadcast_secs = 120;
-    // moduleConfig.detection_sensor.detection_triggered_high = false;
+    // moduleConfig.detection_sensor.detection_triggered_high = true;
     // strcpy(moduleConfig.detection_sensor.name, "Motion");
 
     if (moduleConfig.detection_sensor.enabled == false)
@@ -40,10 +41,12 @@ int32_t DetectionSensorModule::runOnce()
         return DELAYED_INTERVAL;
     }
 
+    // LOG_DEBUG("Detection Sensor Module: Current pin state: %i\n", digitalRead(moduleConfig.detection_sensor.monitor_pin));
+
     if ((millis() - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.detection_sensor.minimum_broadcast_secs) &&
         hasDetectionEvent()) {
         sendDetectionMessage();
-        return DELAYED_INTERVAL;
+        return moduleConfig.detection_sensor.minimum_broadcast_secs;
     }
     // Even if we haven't detected an event, broadcast our current state to the mesh on the scheduled interval as a sort
     // of heartbeat. We only do this if the minimum broadcast interval is greater than zero, otherwise we'll only broadcast state
@@ -51,7 +54,7 @@ int32_t DetectionSensorModule::runOnce()
     else if (moduleConfig.detection_sensor.state_broadcast_secs > 0 &&
              (millis() - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.detection_sensor.state_broadcast_secs)) {
         sendCurrentStateMessage();
-        return DELAYED_INTERVAL;
+        return moduleConfig.detection_sensor.minimum_broadcast_secs;
     }
     return GPIO_POLLING_INTERVAL;
 }

From 91eb64d7b741f20300316f4f0a4d2aff193250f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= 
Date: Wed, 16 Aug 2023 03:17:15 +0200
Subject: [PATCH 22/24] Fix warning about init order (#2725)

---
 src/modules/NeighborInfoModule.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/modules/NeighborInfoModule.cpp b/src/modules/NeighborInfoModule.cpp
index 6d800f37e..706b1db58 100644
--- a/src/modules/NeighborInfoModule.cpp
+++ b/src/modules/NeighborInfoModule.cpp
@@ -88,9 +88,9 @@ void NeighborInfoModule::printNodeDBSelection(const char *header, const meshtast
 
 /* Send our initial owner announcement 35 seconds after we start (to give network time to setup) */
 NeighborInfoModule::NeighborInfoModule()
-    : neighbors(neighborState.neighbors), numNeighbors(&neighborState.neighbors_count),
-      ProtobufModule("neighborinfo", meshtastic_PortNum_NEIGHBORINFO_APP, &meshtastic_NeighborInfo_msg), concurrency::OSThread(
-                                                                                                             "NeighborInfoModule")
+    : ProtobufModule("neighborinfo", meshtastic_PortNum_NEIGHBORINFO_APP, &meshtastic_NeighborInfo_msg),
+      concurrency::OSThread("NeighborInfoModule"), neighbors(neighborState.neighbors),
+      numNeighbors(&neighborState.neighbors_count)
 {
     ourPortNum = meshtastic_PortNum_NEIGHBORINFO_APP;
 

From 5d76771fabf64496ec860ea3a5ce50b437377759 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= 
Date: Wed, 16 Aug 2023 22:07:22 +0200
Subject: [PATCH 23/24] Permanently Enable Canned Messages on T-Deck and
 Picomputer (#2728)

* - Permanently Enable Canned Messages on T-Deck and Picomputer
- picomputer has a really dark TFT; switch color to white for better UX.

* well, you know... bullock...
---
 src/configuration.h                 |  3 +++
 src/graphics/TFTDisplay.cpp         |  4 ++--
 src/modules/CannedMessageModule.cpp | 10 +++++-----
 src/modules/CannedMessageModule.h   |  4 ++++
 variants/picomputer-s3/variant.h    |  5 +++++
 variants/t-deck/variant.h           |  1 +
 6 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/configuration.h b/src/configuration.h
index aa9064251..fb96430bc 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -147,6 +147,9 @@ along with this program.  If not, see .
 #define GPS_THREAD_INTERVAL 100
 #endif
 
+// convert 24-bit color to 16-bit (56K)
+#define COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3))
+
 /* Step #1: offer chance for variant-specific defines */
 #include "variant.h"
 
diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp
index a9611d888..71ce35e82 100644
--- a/src/graphics/TFTDisplay.cpp
+++ b/src/graphics/TFTDisplay.cpp
@@ -4,9 +4,9 @@
 #define TFT_BACKLIGHT_ON HIGH
 #endif
 
-// convert 24-bit color to 16-bit (56K)
-#define COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3))
+#ifndef TFT_MESH
 #define TFT_MESH COLOR565(0x67, 0xEA, 0x94)
+#endif
 
 #if defined(ST7735S)
 #include  // Graphics and font library for ST7735 driver chip
diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp
index e1267ba2a..1e605656f 100644
--- a/src/modules/CannedMessageModule.cpp
+++ b/src/modules/CannedMessageModule.cpp
@@ -63,10 +63,10 @@ CannedMessageModule *cannedMessageModule;
 CannedMessageModule::CannedMessageModule()
     : SinglePortModule("canned", meshtastic_PortNum_TEXT_MESSAGE_APP), concurrency::OSThread("CannedMessageModule")
 {
-    if (moduleConfig.canned_message.enabled) {
+    if (moduleConfig.canned_message.enabled || CANNED_MESSAGE_MODULE_ENABLE) {
         this->loadProtoForModule();
         if ((this->splitConfiguredMessages() <= 0) && (cardkb_found.address != CARDKB_ADDR) &&
-            (cardkb_found.address != TDECK_KB_ADDR) && !INPUTBROKER_MATRIX_TYPE) {
+            (cardkb_found.address != TDECK_KB_ADDR) && !INPUTBROKER_MATRIX_TYPE && !CANNED_MESSAGE_MODULE_ENABLE) {
             LOG_INFO("CannedMessageModule: No messages are configured. Module is disabled\n");
             this->runState = CANNED_MESSAGE_RUN_STATE_DISABLED;
             disable();
@@ -237,8 +237,8 @@ void CannedMessageModule::sendText(NodeNum dest, const char *message, bool wantR
 
 int32_t CannedMessageModule::runOnce()
 {
-    if ((!moduleConfig.canned_message.enabled) || (this->runState == CANNED_MESSAGE_RUN_STATE_DISABLED) ||
-        (this->runState == CANNED_MESSAGE_RUN_STATE_INACTIVE)) {
+    if (((!moduleConfig.canned_message.enabled) && !CANNED_MESSAGE_MODULE_ENABLE) ||
+        (this->runState == CANNED_MESSAGE_RUN_STATE_DISABLED) || (this->runState == CANNED_MESSAGE_RUN_STATE_INACTIVE)) {
         return INT32_MAX;
     }
     // LOG_DEBUG("Check status\n");
@@ -454,7 +454,7 @@ const char *CannedMessageModule::getNodeName(NodeNum node)
 
 bool CannedMessageModule::shouldDraw()
 {
-    if (!moduleConfig.canned_message.enabled) {
+    if (!moduleConfig.canned_message.enabled && !CANNED_MESSAGE_MODULE_ENABLE) {
         return false;
     }
     return (currentMessageIndex != -1) || (this->runState != CANNED_MESSAGE_RUN_STATE_INACTIVE);
diff --git a/src/modules/CannedMessageModule.h b/src/modules/CannedMessageModule.h
index 4e9dadccf..98467215e 100644
--- a/src/modules/CannedMessageModule.h
+++ b/src/modules/CannedMessageModule.h
@@ -20,6 +20,10 @@ enum cannedMessageModuleRunState {
  */
 #define CANNED_MESSAGE_MODULE_MESSAGES_SIZE 800
 
+#ifndef CANNED_MESSAGE_MODULE_ENABLE
+#define CANNED_MESSAGE_MODULE_ENABLE 0
+#endif
+
 class CannedMessageModule : public SinglePortModule, public Observable, private concurrency::OSThread
 {
     CallbackObserver inputObserver =
diff --git a/variants/picomputer-s3/variant.h b/variants/picomputer-s3/variant.h
index 197eb3da1..716f2779d 100644
--- a/variants/picomputer-s3/variant.h
+++ b/variants/picomputer-s3/variant.h
@@ -43,6 +43,11 @@
 #define SCREEN_ROTATE
 #define SCREEN_TRANSITION_FRAMERATE 5
 
+// Picomputer gets a white on black display
+#define TFT_MESH COLOR565(0xFF, 0xFF, 0xFF)
+
+#define CANNED_MESSAGE_MODULE_ENABLE 1
+
 #define INPUTBROKER_MATRIX_TYPE 1
 
 #define KEYS_COLS                                                                                                                \
diff --git a/variants/t-deck/variant.h b/variants/t-deck/variant.h
index c00229ab9..2f4643fde 100644
--- a/variants/t-deck/variant.h
+++ b/variants/t-deck/variant.h
@@ -49,6 +49,7 @@
 #define KB_POWERON 10                  // must be set to HIGH
 #define KB_SLAVE_ADDRESS TDECK_KB_ADDR // 0x55
 #define KB_BL_PIN 46                   // not used for now
+#define CANNED_MESSAGE_MODULE_ENABLE 1
 
 // trackball
 #define HAS_TRACKBALL 1

From 929b8f62096a4b735de67f2eacce6ada3f295cb4 Mon Sep 17 00:00:00 2001
From: Ben Meadors 
Date: Wed, 16 Aug 2023 15:08:06 -0500
Subject: [PATCH 24/24] Fix thread to use getConfiguredOrDefaultMs (#2727)

* WIP

* Updates

* Move it out of the macro guard so portduino can build

* Changes from feedback

* Use minimum_broadcast_secs as interval if we just broadcasted to avoid wasting cpu cycles

* Fmt

* Merge conflict resolution boogered me up

* Missed a spot

* getConfiguredOrDefaultMs

* Get the minimum interval
---
 src/modules/DetectionSensorModule.cpp | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/modules/DetectionSensorModule.cpp b/src/modules/DetectionSensorModule.cpp
index c6f71eb56..c8eb7793b 100644
--- a/src/modules/DetectionSensorModule.cpp
+++ b/src/modules/DetectionSensorModule.cpp
@@ -46,7 +46,10 @@ int32_t DetectionSensorModule::runOnce()
     if ((millis() - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.detection_sensor.minimum_broadcast_secs) &&
         hasDetectionEvent()) {
         sendDetectionMessage();
-        return moduleConfig.detection_sensor.minimum_broadcast_secs;
+        return getConfiguredOrDefaultMs(moduleConfig.detection_sensor.minimum_broadcast_secs <
+                                                moduleConfig.detection_sensor.state_broadcast_secs
+                                            ? moduleConfig.detection_sensor.minimum_broadcast_secs
+                                            : moduleConfig.detection_sensor.state_broadcast_secs);
     }
     // Even if we haven't detected an event, broadcast our current state to the mesh on the scheduled interval as a sort
     // of heartbeat. We only do this if the minimum broadcast interval is greater than zero, otherwise we'll only broadcast state
@@ -54,7 +57,10 @@ int32_t DetectionSensorModule::runOnce()
     else if (moduleConfig.detection_sensor.state_broadcast_secs > 0 &&
              (millis() - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.detection_sensor.state_broadcast_secs)) {
         sendCurrentStateMessage();
-        return moduleConfig.detection_sensor.minimum_broadcast_secs;
+        return getConfiguredOrDefaultMs(moduleConfig.detection_sensor.minimum_broadcast_secs <
+                                                moduleConfig.detection_sensor.state_broadcast_secs
+                                            ? moduleConfig.detection_sensor.minimum_broadcast_secs
+                                            : moduleConfig.detection_sensor.state_broadcast_secs);
     }
     return GPIO_POLLING_INTERVAL;
 }