diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e45fd5d93..d83d052b0 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -13,16 +13,13 @@ }, "customizations": { "vscode": { - "extensions": [ - "ms-vscode.cpptools", - "platformio.platformio-ide", - ] + "extensions": ["ms-vscode.cpptools", "platformio.platformio-ide"] } }, // Use 'forwardPorts' to make a list of ports inside the container available locally. - "forwardPorts": [ 4403 ], + "forwardPorts": [4403], // Run commands to prepare the container for use - "postCreateCommand": ".devcontainer/setup.sh", + "postCreateCommand": ".devcontainer/setup.sh" } diff --git a/.devcontainer/setup.sh b/.devcontainer/setup.sh index 866a4a417..0b2665f84 100755 --- a/.devcontainer/setup.sh +++ b/.devcontainer/setup.sh @@ -1,3 +1,3 @@ #!/usr/bin/env sh -git submodule update --init \ No newline at end of file +git submodule update --init diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 925b91215..241598fd0 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -65,7 +65,7 @@ jobs: # - uses: actions/setup-python@v5 # with: # python-version: '3.10' - + # pipx install "setuptools<72" - name: Upgrade python tools shell: bash @@ -76,10 +76,10 @@ jobs: - name: Install PlatformIO from script shell: bash - run: | + run: | curl -fsSL -o get-platformio.py https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py python3 get-platformio.py - + - name: Upgrade platformio shell: bash run: | @@ -90,7 +90,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: 18 - + - name: Setup pnpm uses: pnpm/action-setup@v4 with: diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..fb4d9005a --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,12 @@ +# Security Policy + +## Supported Versions + +| Firmware Version | Supported | +| ---------------- | ------------------ | +| 2.5.x | :white_check_mark: | +| <= 2.4.x | :x: | + +## Reporting a Vulnerability + +We support the private reporting of potential security vulnerabilities. Please go to the Security tab to file a report with a description of the potential vulnerability and reproduction scripts (preferred) or steps, and our developers will review. diff --git a/src/Power.cpp b/src/Power.cpp index bbb6cd2c3..c71d17586 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -147,6 +147,8 @@ using namespace meshtastic; */ static HasBatteryLevel *batteryLevel; // Default to NULL for no battery level sensor +#ifdef BATTERY_PIN + static void adcEnable() { #ifdef ADC_CTRL // enable adc voltage divider when we need to read @@ -171,6 +173,8 @@ static void adcDisable() #endif } +#endif + /** * A simple battery level sensor that assumes the battery voltage is attached via a voltage-divider to an analog input */ diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 285f3a2fd..b13ca4b06 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -7,6 +7,7 @@ #include "PowerMon.h" #include "RTC.h" #include "Throttle.h" +#include "meshUtils.h" #include "main.h" // pmu_found #include "sleep.h" @@ -511,7 +512,7 @@ bool GPS::setup() delay(250); _serial_gps->write("$CFGMSG,6,1,0\r\n"); delay(250); - } else if (gnssModel == GNSS_MODEL_AG3335 || gnssModel == GNSS_MODEL_AG3352) { + } else if (IS_ONE_OF(gnssModel, GNSS_MODEL_AG3335, GNSS_MODEL_AG3352)) { _serial_gps->write("$PAIR066,1,0,1,0,0,1*3B\r\n"); // Enable GPS+GALILEO+NAVIC @@ -553,7 +554,7 @@ bool GPS::setup() } else { LOG_INFO("GNSS module configuration saved!\n"); } - } else if (gnssModel == GNSS_MODEL_UBLOX7 || gnssModel == GNSS_MODEL_UBLOX8 || gnssModel == GNSS_MODEL_UBLOX9) { + } else if (IS_ONE_OF(gnssModel, GNSS_MODEL_UBLOX7, GNSS_MODEL_UBLOX8, GNSS_MODEL_UBLOX9)) { if (gnssModel == GNSS_MODEL_UBLOX7) { LOG_DEBUG("Setting GPS+SBAS\n"); msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_7), _message_GNSS_7); @@ -826,8 +827,7 @@ void GPS::setPowerPMU(bool on) void GPS::setPowerUBLOX(bool on, uint32_t sleepMs) { // Abort: if not UBLOX hardware - if (!(gnssModel == GNSS_MODEL_UBLOX6 || gnssModel == GNSS_MODEL_UBLOX7 || gnssModel == GNSS_MODEL_UBLOX8 || - gnssModel == GNSS_MODEL_UBLOX9 || gnssModel == GNSS_MODEL_UBLOX10)) + if (!IS_ONE_OF(gnssModel, GNSS_MODEL_UBLOX6, GNSS_MODEL_UBLOX7, GNSS_MODEL_UBLOX8, GNSS_MODEL_UBLOX9, GNSS_MODEL_UBLOX10)) return; // If waking @@ -910,8 +910,7 @@ void GPS::down() // If not, fallback to GPS_HARDSLEEP instead bool softsleepSupported = false; // U-blox is supported via PMREQ - if (gnssModel == GNSS_MODEL_UBLOX6 || gnssModel == GNSS_MODEL_UBLOX7 || gnssModel == GNSS_MODEL_UBLOX8 || - gnssModel == GNSS_MODEL_UBLOX9 || gnssModel == GNSS_MODEL_UBLOX10) + if (IS_ONE_OF(gnssModel, GNSS_MODEL_UBLOX6, GNSS_MODEL_UBLOX7, GNSS_MODEL_UBLOX8, GNSS_MODEL_UBLOX9, GNSS_MODEL_UBLOX10)) softsleepSupported = true; #ifdef PIN_GPS_STANDBY // L76B, L76K and clones have a standby pin softsleepSupported = true; @@ -987,8 +986,8 @@ int32_t GPS::runOnce() setConnected(); } else { if ((config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) && - (gnssModel == GNSS_MODEL_UBLOX6 || gnssModel == GNSS_MODEL_UBLOX7 || gnssModel == GNSS_MODEL_UBLOX8 || - gnssModel == GNSS_MODEL_UBLOX9 || gnssModel == GNSS_MODEL_UBLOX10)) { + IS_ONE_OF(gnssModel, GNSS_MODEL_UBLOX6, GNSS_MODEL_UBLOX7, GNSS_MODEL_UBLOX8, GNSS_MODEL_UBLOX9, + GNSS_MODEL_UBLOX10)) { // reset the GPS on next bootup if (devicestate.did_gps_reset && scheduling.elapsedSearchMs() > 60 * 1000UL && !hasFlow()) { LOG_DEBUG("GPS is not communicating, trying factory reset on next bootup.\n"); diff --git a/src/main.cpp b/src/main.cpp index fa032a209..0d37e8f46 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,6 +32,7 @@ #include "graphics/Screen.h" #include "main.h" #include "mesh/generated/meshtastic/config.pb.h" +#include "meshUtils.h" #include "modules/Modules.h" #include "shutdown.h" #include "sleep.h" @@ -628,9 +629,9 @@ void setup() #endif // only play start melody when role is not tracker or sensor - if (config.power.is_power_saving == true && (config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER || - config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER || - config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR)) + if (config.power.is_power_saving == true && + IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_TRACKER, + meshtastic_Config_DeviceConfig_Role_TAK_TRACKER, meshtastic_Config_DeviceConfig_Role_SENSOR)) LOG_DEBUG("Tracker/Sensor: Skipping start melody\n"); else playStartMelody(); diff --git a/src/mesh/LR11x0Interface.cpp b/src/mesh/LR11x0Interface.cpp index 9e911107a..00d84dc0d 100644 --- a/src/mesh/LR11x0Interface.cpp +++ b/src/mesh/LR11x0Interface.cpp @@ -296,29 +296,8 @@ template bool LR11x0Interface::isActivelyReceiving() { // The IRQ status will be cleared when we start our read operation. Check if we've started a header, but haven't yet // received and handled the interrupt for reading the packet/handling errors. - - uint16_t irq = lora.getIrqStatus(); - bool detected = (irq & (RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID | RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED)); - // Handle false detections - if (detected) { - if (!activeReceiveStart) { - activeReceiveStart = millis(); - } else if (!Throttle::isWithinTimespanMs(activeReceiveStart, 2 * preambleTimeMsec) && - !(irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID)) { - // The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag - activeReceiveStart = 0; - LOG_DEBUG("Ignore false preamble detection.\n"); - return false; - } else if (!Throttle::isWithinTimespanMs(activeReceiveStart, maxPacketTimeMsec)) { - // We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag - activeReceiveStart = 0; - LOG_DEBUG("Ignore false header detection.\n"); - return false; - } - } - - // if (detected) LOG_DEBUG("rx detected\n"); - return detected; + return receiveDetected(lora.getIrqStatus(), RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID, + RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED); } template bool LR11x0Interface::sleep() diff --git a/src/mesh/LR11x0Interface.h b/src/mesh/LR11x0Interface.h index 9272f43f0..5711b1f7f 100644 --- a/src/mesh/LR11x0Interface.h +++ b/src/mesh/LR11x0Interface.h @@ -65,7 +65,4 @@ template class LR11x0Interface : public RadioLibInterface virtual void addReceiveMetadata(meshtastic_MeshPacket *mp) override; virtual void setStandby() override; - - private: - uint32_t activeReceiveStart = 0; }; diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index c94a7653c..c3ebf3c6e 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -2,6 +2,7 @@ #include "Observer.h" #include +#include #include #include diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index 6cdb3b99e..0968a6d89 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -129,6 +129,28 @@ bool RadioLibInterface::canSendImmediately() return true; } +bool RadioLibInterface::receiveDetected(uint16_t irq, ulong syncWordHeaderValidFlag, ulong preambleDetectedFlag) +{ + bool detected = (irq & (syncWordHeaderValidFlag | preambleDetectedFlag)); + // Handle false detections + if (detected) { + if (!activeReceiveStart) { + activeReceiveStart = millis(); + } else if (!Throttle::isWithinTimespanMs(activeReceiveStart, 2 * preambleTimeMsec) && !(irq & syncWordHeaderValidFlag)) { + // The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag + activeReceiveStart = 0; + LOG_DEBUG("Ignore false preamble detection.\n"); + return false; + } else if (!Throttle::isWithinTimespanMs(activeReceiveStart, maxPacketTimeMsec)) { + // We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag + activeReceiveStart = 0; + LOG_DEBUG("Ignore false header detection.\n"); + return false; + } + } + return detected; +} + /// Send a packet (possibly by enquing in a private fifo). This routine will /// later free() the packet to pool. This routine is not allowed to stall because it is called from /// bluetooth comms code. If the txmit queue is empty it might return an error diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h index edcbb394f..13bef851a 100644 --- a/src/mesh/RadioLibInterface.h +++ b/src/mesh/RadioLibInterface.h @@ -167,6 +167,10 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified meshtastic_QueueStatus getQueueStatus(); protected: + uint32_t activeReceiveStart = 0; + + bool receiveDetected(uint16_t irq, ulong syncWordHeaderValidFlag, ulong preambleDetectedFlag); + /** Do any hardware setup needed on entry into send configuration for the radio. * Subclasses can customize, but must also call this base method */ virtual void configHardwareForSend(); diff --git a/src/mesh/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp index 2c6096062..ad1ceeeeb 100644 --- a/src/mesh/SX126xInterface.cpp +++ b/src/mesh/SX126xInterface.cpp @@ -316,29 +316,7 @@ template bool SX126xInterface::isActivelyReceiving() { // The IRQ status will be cleared when we start our read operation. Check if we've started a header, but haven't yet // received and handled the interrupt for reading the packet/handling errors. - - uint16_t irq = lora.getIrqFlags(); - bool detected = (irq & (RADIOLIB_SX126X_IRQ_HEADER_VALID | RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED)); - // Handle false detections - if (detected) { - if (!activeReceiveStart) { - activeReceiveStart = millis(); - } else if (!Throttle::isWithinTimespanMs(activeReceiveStart, 2 * preambleTimeMsec) && - !(irq & RADIOLIB_SX126X_IRQ_HEADER_VALID)) { - // The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag - activeReceiveStart = 0; - LOG_DEBUG("Ignore false preamble detection.\n"); - return false; - } else if (!Throttle::isWithinTimespanMs(activeReceiveStart, maxPacketTimeMsec)) { - // We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag - activeReceiveStart = 0; - LOG_DEBUG("Ignore false header detection.\n"); - return false; - } - } - - // if (detected) LOG_DEBUG("rx detected\n"); - return detected; + return receiveDetected(lora.getIrqFlags(), RADIOLIB_SX126X_IRQ_HEADER_VALID, RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED); } template bool SX126xInterface::sleep() diff --git a/src/mesh/SX126xInterface.h b/src/mesh/SX126xInterface.h index b392cd3e4..c437080c4 100644 --- a/src/mesh/SX126xInterface.h +++ b/src/mesh/SX126xInterface.h @@ -67,7 +67,4 @@ template class SX126xInterface : public RadioLibInterface virtual void addReceiveMetadata(meshtastic_MeshPacket *mp) override; virtual void setStandby() override; - - private: - uint32_t activeReceiveStart = 0; }; diff --git a/src/mesh/SX128xInterface.cpp b/src/mesh/SX128xInterface.cpp index 270356e26..5c740099c 100644 --- a/src/mesh/SX128xInterface.cpp +++ b/src/mesh/SX128xInterface.cpp @@ -290,28 +290,7 @@ template bool SX128xInterface::isChannelActive() /** Could we send right now (i.e. either not actively receiving or transmitting)? */ template bool SX128xInterface::isActivelyReceiving() { - uint16_t irq = lora.getIrqStatus(); - bool detected = (irq & (RADIOLIB_SX128X_IRQ_HEADER_VALID | RADIOLIB_SX128X_IRQ_PREAMBLE_DETECTED)); - - // Handle false detections - if (detected) { - if (!activeReceiveStart) { - activeReceiveStart = millis(); - } else if (!Throttle::isWithinTimespanMs(activeReceiveStart, 2 * preambleTimeMsec) && - !(irq & RADIOLIB_SX128X_IRQ_HEADER_VALID)) { - // The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag - activeReceiveStart = 0; - LOG_DEBUG("Ignore false preamble detection.\n"); - return false; - } else if (Throttle::isWithinTimespanMs(activeReceiveStart, maxPacketTimeMsec)) { - // We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag - activeReceiveStart = 0; - LOG_DEBUG("Ignore false header detection.\n"); - return false; - } - } - - return detected; + return receiveDetected(lora.getIrqStatus(), RADIOLIB_SX128X_IRQ_HEADER_VALID, RADIOLIB_SX128X_IRQ_PREAMBLE_DETECTED); } template bool SX128xInterface::sleep() diff --git a/src/mesh/SX128xInterface.h b/src/mesh/SX128xInterface.h index f7fd35b25..bba31dab4 100644 --- a/src/mesh/SX128xInterface.h +++ b/src/mesh/SX128xInterface.h @@ -67,7 +67,4 @@ template class SX128xInterface : public RadioLibInterface virtual void addReceiveMetadata(meshtastic_MeshPacket *mp) override; virtual void setStandby() override; - - private: - uint32_t activeReceiveStart = 0; }; diff --git a/src/meshUtils.cpp b/src/meshUtils.cpp index 4819f6ed7..853193a12 100644 --- a/src/meshUtils.cpp +++ b/src/meshUtils.cpp @@ -80,4 +80,19 @@ bool memfll(const uint8_t *mem, uint8_t find, size_t numbytes) return false; } return true; +} + +bool isOneOf(int item, int count, ...) +{ + va_list args; + va_start(args, count); + bool found = false; + for (int i = 0; i < count; ++i) { + if (item == va_arg(args, int)) { + found = true; + break; + } + } + va_end(args); + return found; } \ No newline at end of file diff --git a/src/meshUtils.h b/src/meshUtils.h index ce063cb6a..aff3976f4 100644 --- a/src/meshUtils.h +++ b/src/meshUtils.h @@ -1,5 +1,8 @@ #pragma once #include "DebugConfiguration.h" +#include +#include +#include #include /// C++ v17+ clamp function, limits a given value to a range defined by lo and hi @@ -17,4 +20,8 @@ char *strnstr(const char *s, const char *find, size_t slen); void printBytes(const char *label, const uint8_t *p, size_t numbytes); // is the memory region filled with a single character? -bool memfll(const uint8_t *mem, uint8_t find, size_t numbytes); \ No newline at end of file +bool memfll(const uint8_t *mem, uint8_t find, size_t numbytes); + +bool isOneOf(int item, int count, ...); + +#define IS_ONE_OF(item, ...) isOneOf(item, sizeof((int[]){__VA_ARGS__}) / sizeof(int), __VA_ARGS__) diff --git a/src/modules/DetectionSensorModule.cpp b/src/modules/DetectionSensorModule.cpp index cb63b2c1a..eb13616de 100644 --- a/src/modules/DetectionSensorModule.cpp +++ b/src/modules/DetectionSensorModule.cpp @@ -11,6 +11,41 @@ DetectionSensorModule *detectionSensorModule; #define GPIO_POLLING_INTERVAL 100 #define DELAYED_INTERVAL 1000 +typedef enum { + DetectionSensorVerdictDetected, + DetectionSensorVerdictSendState, + DetectionSensorVerdictNoop, +} DetectionSensorTriggerVerdict; + +typedef DetectionSensorTriggerVerdict (*DetectionSensorTriggerHandler)(bool prev, bool current); + +static DetectionSensorTriggerVerdict detection_trigger_logic_level(bool prev, bool current) +{ + return current ? DetectionSensorVerdictDetected : DetectionSensorVerdictNoop; +} + +static DetectionSensorTriggerVerdict detection_trigger_single_edge(bool prev, bool current) +{ + return (!prev && current) ? DetectionSensorVerdictDetected : DetectionSensorVerdictNoop; +} + +static DetectionSensorTriggerVerdict detection_trigger_either_edge(bool prev, bool current) +{ + if (prev == current) { + return DetectionSensorVerdictNoop; + } + return current ? DetectionSensorVerdictDetected : DetectionSensorVerdictSendState; +} + +const static DetectionSensorTriggerHandler handlers[_meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_MAX + 1] = { + [meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_LOGIC_LOW] = detection_trigger_logic_level, + [meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_LOGIC_HIGH] = detection_trigger_logic_level, + [meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_FALLING_EDGE] = detection_trigger_single_edge, + [meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_RISING_EDGE] = detection_trigger_single_edge, + [meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_EITHER_EDGE_ACTIVE_LOW] = detection_trigger_either_edge, + [meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_EITHER_EDGE_ACTIVE_HIGH] = detection_trigger_either_edge, +}; + int32_t DetectionSensorModule::runOnce() { /* @@ -22,7 +57,8 @@ int32_t DetectionSensorModule::runOnce() // 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 = true; + // moduleConfig.detection_sensor.detection_trigger_type = + // meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_LOGIC_HIGH; // strcpy(moduleConfig.detection_sensor.name, "Motion"); if (moduleConfig.detection_sensor.enabled == false) @@ -51,19 +87,30 @@ int32_t DetectionSensorModule::runOnce() // LOG_DEBUG("Detection Sensor Module: Current pin state: %i\n", digitalRead(moduleConfig.detection_sensor.monitor_pin)); if (!Throttle::isWithinTimespanMs(lastSentToMesh, - Default::getConfiguredOrDefaultMs(moduleConfig.detection_sensor.minimum_broadcast_secs)) && - hasDetectionEvent()) { - sendDetectionMessage(); - return DELAYED_INTERVAL; + Default::getConfiguredOrDefaultMs(moduleConfig.detection_sensor.minimum_broadcast_secs))) { + bool isDetected = hasDetectionEvent(); + DetectionSensorTriggerVerdict verdict = + handlers[moduleConfig.detection_sensor.detection_trigger_type](wasDetected, isDetected); + wasDetected = isDetected; + switch (verdict) { + case DetectionSensorVerdictDetected: + sendDetectionMessage(); + return DELAYED_INTERVAL; + case DetectionSensorVerdictSendState: + sendCurrentStateMessage(isDetected); + return DELAYED_INTERVAL; + case DetectionSensorVerdictNoop: + break; + } } // 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 && - !Throttle::isWithinTimespanMs(lastSentToMesh, - Default::getConfiguredOrDefaultMs(moduleConfig.detection_sensor.state_broadcast_secs, - default_telemetry_broadcast_interval_secs))) { - sendCurrentStateMessage(); + if (moduleConfig.detection_sensor.state_broadcast_secs > 0 && + !Throttle::isWithinTimespanMs(lastSentToMesh, + Default::getConfiguredOrDefaultMs(moduleConfig.detection_sensor.state_broadcast_secs, + default_telemetry_broadcast_interval_secs))) { + sendCurrentStateMessage(hasDetectionEvent()); return DELAYED_INTERVAL; } return GPIO_POLLING_INTERVAL; @@ -89,10 +136,10 @@ void DetectionSensorModule::sendDetectionMessage() delete[] message; } -void DetectionSensorModule::sendCurrentStateMessage() +void DetectionSensorModule::sendCurrentStateMessage(bool state) { char *message = new char[40]; - sprintf(message, "%s state: %i", moduleConfig.detection_sensor.name, hasDetectionEvent()); + sprintf(message, "%s state: %i", moduleConfig.detection_sensor.name, state); meshtastic_MeshPacket *p = allocDataPacket(); p->want_ack = false; @@ -108,5 +155,5 @@ 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_trigger_type ? currentState : !currentState; + return (moduleConfig.detection_sensor.detection_trigger_type & 1) ? currentState : !currentState; } \ No newline at end of file diff --git a/src/modules/DetectionSensorModule.h b/src/modules/DetectionSensorModule.h index ed6cddda5..b960c8744 100644 --- a/src/modules/DetectionSensorModule.h +++ b/src/modules/DetectionSensorModule.h @@ -15,8 +15,9 @@ class DetectionSensorModule : public SinglePortModule, private concurrency::OSTh private: bool firstTime = true; uint32_t lastSentToMesh = 0; + bool wasDetected = false; void sendDetectionMessage(); - void sendCurrentStateMessage(); + void sendCurrentStateMessage(bool state); bool hasDetectionEvent(); }; diff --git a/src/modules/PositionModule.cpp b/src/modules/PositionModule.cpp index 4ba09385d..6ae990bab 100644 --- a/src/modules/PositionModule.cpp +++ b/src/modules/PositionModule.cpp @@ -12,6 +12,7 @@ #include "gps/GeoCoord.h" #include "main.h" #include "mesh/compression/unishox2.h" +#include "meshUtils.h" #include "meshtastic/atak.pb.h" #include "sleep.h" #include "target_specific.h" @@ -347,8 +348,8 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha service->sendToMesh(p, RX_SRC_LOCAL, true); - if ((config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER || - config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) && + if (IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_TRACKER, + meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) && config.power.is_power_saving) { LOG_DEBUG("Starting next execution in 5 seconds and then going to sleep.\n"); sleepOnNextExecution = true; diff --git a/src/modules/Telemetry/DeviceTelemetry.cpp b/src/modules/Telemetry/DeviceTelemetry.cpp index 04789af5e..dd5067784 100644 --- a/src/modules/Telemetry/DeviceTelemetry.cpp +++ b/src/modules/Telemetry/DeviceTelemetry.cpp @@ -11,14 +11,15 @@ #include "main.h" #include #include +#include #define MAGIC_USB_BATTERY_LEVEL 101 int32_t DeviceTelemetryModule::runOnce() { refreshUptime(); - bool isImpoliteRole = config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR || - config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER; + bool isImpoliteRole = + IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_SENSOR, meshtastic_Config_DeviceConfig_Role_ROUTER); if (((lastSentToMesh == 0) || ((uptimeLastMs - lastSentToMesh) >= Default::getConfiguredOrDefaultMsScaled(moduleConfig.telemetry.device_update_interval, diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp index 969529881..8f891593a 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.cpp +++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp @@ -158,7 +158,6 @@ int32_t EnvironmentTelemetryModule::runOnce() result = bme680Sensor.runTrigger(); } - uint32_t now = millis(); if (((lastSentToMesh == 0) || !Throttle::isWithinTimespanMs(lastSentToMesh, Default::getConfiguredOrDefaultMsScaled( moduleConfig.telemetry.environment_update_interval, diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index 56af9f663..2ce5cd755 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -32,6 +32,9 @@ static MemoryDynamic staticMqttPool; Allocator &mqttPool = staticMqttPool; +// FIXME - this size calculation is super sloppy, but it will go away once we dynamically alloc meshpackets +static uint8_t bytes[meshtastic_MqttClientProxyMessage_size + 30]; // 12 for channel name and 16 for nodeid + void MQTT::mqttCallback(char *topic, byte *payload, unsigned int length) { mqtt->onReceive(topic, payload, length); @@ -482,9 +485,7 @@ void MQTT::publishQueuedMessages() { if (!mqttQueue.isEmpty()) { LOG_DEBUG("Publishing enqueued MQTT message\n"); - // FIXME - this size calculation is super sloppy, but it will go away once we dynamically alloc meshpackets meshtastic_ServiceEnvelope *env = mqttQueue.dequeuePtr(0); - static uint8_t bytes[meshtastic_MqttClientProxyMessage_size]; size_t numBytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_ServiceEnvelope_msg, env); std::string topic; if (env->packet->pki_encrypted) { @@ -570,8 +571,6 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp, const meshtastic_MeshPacket & } if (moduleConfig.mqtt.proxy_to_client_enabled || this->isConnectedDirectly()) { - // FIXME - this size calculation is super sloppy, but it will go away once we dynamically alloc meshpackets - static uint8_t bytes[meshtastic_MqttClientProxyMessage_size]; size_t numBytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_ServiceEnvelope_msg, env); std::string topic = cryptTopic + channelId + "/" + owner.id; LOG_DEBUG("MQTT Publish %s, %u bytes\n", topic.c_str(), numBytes); @@ -666,8 +665,6 @@ void MQTT::perhapsReportToMap() &meshtastic_MapReport_msg, &mapReport); se->packet = mp; - // FIXME - this size calculation is super sloppy, but it will go away once we dynamically alloc meshpackets - static uint8_t bytes[meshtastic_MqttClientProxyMessage_size]; size_t numBytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_ServiceEnvelope_msg, se); LOG_INFO("MQTT Publish map report to %s\n", mapTopic.c_str()); diff --git a/src/platform/nrf52/main-nrf52.cpp b/src/platform/nrf52/main-nrf52.cpp index b28640e65..4023a3cb9 100644 --- a/src/platform/nrf52/main-nrf52.cpp +++ b/src/platform/nrf52/main-nrf52.cpp @@ -12,6 +12,7 @@ #include "PowerMon.h" #include "error.h" #include "main.h" +#include "meshUtils.h" #ifdef BQ25703A_ADDR #include "BQ25713.h" @@ -157,6 +158,7 @@ void nrf52Loop() #ifdef USE_SEMIHOSTING #include +#include /** * Note: this variable is in BSS and therfore false by default. But the gdbinit @@ -261,10 +263,9 @@ void cpuDeepSleep(uint32_t msecToWake) // Sleepy trackers or sensors can low power "sleep" // Don't enter this if we're sleeping portMAX_DELAY, since that's a shutdown event if (msecToWake != portMAX_DELAY && - (config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER || - config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER || - config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR) && - config.power.is_power_saving == true) { + (IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_TRACKER, + meshtastic_Config_DeviceConfig_Role_TAK_TRACKER, meshtastic_Config_DeviceConfig_Role_SENSOR) && + config.power.is_power_saving == true)) { sd_power_mode_set(NRF_POWER_MODE_LOWPWR); delay(msecToWake); NVIC_SystemReset();