From d29c975e3c9c590e27f07b5658bcb4e40b7b6355 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sat, 12 Aug 2023 13:51:31 -0500 Subject: [PATCH 01/10] 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 02/10] 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 03/10] [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 04/10] 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 05/10] 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 06/10] 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 07/10] 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 08/10] 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 09/10] 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 10/10] 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; }