From 198b62f3fcc1c427c4b5ed1cc03168e89dbab56d Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 16 Oct 2024 07:34:24 -0500 Subject: [PATCH 01/20] I thought these were already board level extra --- variants/heltec_v2.1/platformio.ini | 1 + variants/heltec_v2/platformio.ini | 3 ++- variants/tlora_v2/platformio.ini | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/variants/heltec_v2.1/platformio.ini b/variants/heltec_v2.1/platformio.ini index 5aa04fc58..ea2281911 100644 --- a/variants/heltec_v2.1/platformio.ini +++ b/variants/heltec_v2.1/platformio.ini @@ -1,4 +1,5 @@ [env:heltec-v2_1] +board_level = extra ;build_type = debug ; to make it possible to step through our jtag debugger extends = esp32_base board = heltec_wifi_lora_32_V2 diff --git a/variants/heltec_v2/platformio.ini b/variants/heltec_v2/platformio.ini index cee1537d0..c81bca8ba 100644 --- a/variants/heltec_v2/platformio.ini +++ b/variants/heltec_v2/platformio.ini @@ -1,5 +1,6 @@ [env:heltec-v2_0] -;build_type = debug ; to make it possible to step through our jtag debugger +;build_type = debug ; to make it possible to step through our jtag debugger +board_level = extra extends = esp32_base board = heltec_wifi_lora_32_V2 build_flags = diff --git a/variants/tlora_v2/platformio.ini b/variants/tlora_v2/platformio.ini index 8710068af..8087a30e3 100644 --- a/variants/tlora_v2/platformio.ini +++ b/variants/tlora_v2/platformio.ini @@ -1,4 +1,5 @@ [env:tlora-v2] +board_level = extra extends = esp32_base board = ttgo-lora32-v1 build_flags = From f77c87dca8da0903f4f73d54c0f46ec9619b1e31 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 16 Oct 2024 09:18:44 -0500 Subject: [PATCH 02/20] Extra extra --- variants/tlora_v1/platformio.ini | 1 + variants/tlora_v1_3/platformio.ini | 1 + 2 files changed, 2 insertions(+) diff --git a/variants/tlora_v1/platformio.ini b/variants/tlora_v1/platformio.ini index c90daed90..65ec4bcdc 100644 --- a/variants/tlora_v1/platformio.ini +++ b/variants/tlora_v1/platformio.ini @@ -1,4 +1,5 @@ [env:tlora-v1] +board_level = extra extends = esp32_base board = ttgo-lora32-v1 build_flags = diff --git a/variants/tlora_v1_3/platformio.ini b/variants/tlora_v1_3/platformio.ini index 9d9f41a7c..99df28e56 100644 --- a/variants/tlora_v1_3/platformio.ini +++ b/variants/tlora_v1_3/platformio.ini @@ -1,4 +1,5 @@ [env:tlora_v1_3] +board_level = extra extends = esp32_base board = ttgo-lora32-v1 build_flags = From 2ea2b47690a6c59aee250ccbc9dc9240bbd291c2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 19:51:11 -0500 Subject: [PATCH 03/20] [create-pull-request] automated change (#5085) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- version.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.properties b/version.properties index be97dacb5..327f29443 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 5 -build = 7 +build = 8 From fbb6778415dac8d6e7e33d8c79510f77ecdb42fa Mon Sep 17 00:00:00 2001 From: Johnathon Mohr Date: Thu, 17 Oct 2024 03:05:35 -0700 Subject: [PATCH 04/20] Account for port specification with IP address for MQTT server. Some additional format validation. (#5084) --- src/mqtt/MQTT.cpp | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index 45518153e..3ad397beb 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -706,18 +706,43 @@ bool MQTT::isValidJsonEnvelope(JSONObject &json) bool MQTT::isPrivateIpAddress(const char address[]) { - // Min. length like 10.0.0.0, max like 192.168.255.255 + // Min. length like 10.0.0.0 (8), max like 192.168.255.255:65535 (21) size_t length = strlen(address); - if (length < 8 || length > 15) { + if (length < 8 || length > 21) { return false; } - // Ensure the address contains only digits and dots. + // Ensure the address contains only digits and dots and maybe a colon. + // Some limited validation is done. // Even if it's not a valid IP address, we will know it's not a domain. + bool hasColon = false; + int numDots = 0; for (int i = 0; i < length; i++) { - if (!isdigit(address[i]) && address[i] != '.') { + if (!isdigit(address[i]) && address[i] != '.' && address[i] != ':') { return false; } + + // Dots can't be the first character, immediately follow another dot, + // occur more than 3 times, or occur after a colon. + if (address[i] == '.') { + if (++numDots > 3 || i == 0 || address[i - 1] == '.' || hasColon) { + return false; + } + } + // There can only be a single colon, and it can only occur after 3 dots + else if (address[i] == ':') { + if (hasColon || numDots < 3) { + return false; + } + + hasColon = true; + } + } + + // Final validation for IPv4 address and port format. + // Note that the values of octets haven't been tested, only the address format. + if (numDots != 3) { + return false; } // Check the easy ones first. From ec9e562a770aa0eeac57aea8354c930927bc6ab6 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Thu, 17 Oct 2024 13:33:52 -0500 Subject: [PATCH 05/20] Coerce minimum telemetry interval of 30 minutes on defaults and make new default interval one hour (#5086) * Coerce minimum telemetry interval of 30 minutes on defaults and make new default interval one hour * Smaller log messages --- src/mesh/Default.cpp | 9 +++++++++ src/mesh/Default.h | 4 +++- src/mesh/NodeDB.cpp | 16 ++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/mesh/Default.cpp b/src/mesh/Default.cpp index 0bedcfc91..653528b60 100644 --- a/src/mesh/Default.cpp +++ b/src/mesh/Default.cpp @@ -43,6 +43,15 @@ uint32_t Default::getConfiguredOrDefaultMsScaled(uint32_t configured, uint32_t d return getConfiguredOrDefaultMs(configured, defaultValue) * congestionScalingCoefficient(numOnlineNodes); } +uint32_t Default::getConfiguredOrMinimumValue(uint32_t configured, uint32_t minValue) +{ + // If zero, intervals should be coalesced later by getConfiguredOrDefault... methods + if (configured == 0) + return configured; + + return configured < minValue ? minValue : configured; +} + uint8_t Default::getConfiguredOrDefaultHopLimit(uint8_t configured) { #if USERPREFS_EVENT_MODE diff --git a/src/mesh/Default.h b/src/mesh/Default.h index 5641b5d25..2406dafc5 100644 --- a/src/mesh/Default.h +++ b/src/mesh/Default.h @@ -6,8 +6,9 @@ #define THIRTY_SECONDS_MS 30 * 1000 #define FIVE_SECONDS_MS 5 * 1000 +#define min_default_telemetry_interval_secs 30 * 60 #define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60) -#define default_telemetry_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 30 * 60) +#define default_telemetry_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 60 * 60) #define default_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 15 * 60) #define default_wait_bluetooth_secs IF_ROUTER(1, 60) #define default_sds_secs IF_ROUTER(ONE_DAY, UINT32_MAX) // Default to forever super deep sleep @@ -35,6 +36,7 @@ class Default static uint32_t getConfiguredOrDefault(uint32_t configured, uint32_t defaultValue); static uint32_t getConfiguredOrDefaultMsScaled(uint32_t configured, uint32_t defaultValue, uint32_t numOnlineNodes); static uint8_t getConfiguredOrDefaultHopLimit(uint8_t configured); + static uint32_t getConfiguredOrMinimumValue(uint32_t configured, uint32_t minValue); private: static float congestionScalingCoefficient(int numOnlineNodes) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 558c5b825..ebe3debdb 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -171,6 +171,22 @@ NodeDB::NodeDB() resetRadioConfig(); // If bogus settings got saved, then fix them // nodeDB->LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d", config.lora.region, myNodeInfo.my_node_num, numMeshNodes); + // If we are setup to broadcast on the default channel, ensure that the telemetry intervals are coerced to the minimum value + // of 30 minutes or more + if (channels.isDefaultChannel(channels.getPrimaryIndex())) { + LOG_DEBUG("Coercing telemetry to min of 30 minutes on defaults"); + moduleConfig.telemetry.device_update_interval = Default::getConfiguredOrMinimumValue( + moduleConfig.telemetry.device_update_interval, min_default_telemetry_interval_secs); + moduleConfig.telemetry.environment_update_interval = Default::getConfiguredOrMinimumValue( + moduleConfig.telemetry.environment_update_interval, min_default_telemetry_interval_secs); + moduleConfig.telemetry.air_quality_interval = Default::getConfiguredOrMinimumValue( + moduleConfig.telemetry.air_quality_interval, min_default_telemetry_interval_secs); + moduleConfig.telemetry.power_update_interval = Default::getConfiguredOrMinimumValue( + moduleConfig.telemetry.power_update_interval, min_default_telemetry_interval_secs); + moduleConfig.telemetry.health_update_interval = Default::getConfiguredOrMinimumValue( + moduleConfig.telemetry.health_update_interval, min_default_telemetry_interval_secs); + } + if (devicestateCRC != crc32Buffer(&devicestate, sizeof(devicestate))) saveWhat |= SEGMENT_DEVICESTATE; if (configCRC != crc32Buffer(&config, sizeof(config))) From 934be696634d7ec413bdcff8c70dd47434137e68 Mon Sep 17 00:00:00 2001 From: Technologyman00 Date: Thu, 17 Oct 2024 22:40:18 -0500 Subject: [PATCH 06/20] Add buzzer feedback on GPS toggle (#5090) Triple Press on buttons toggles GPS enable/disable. This enhancement plays a triple-beep so that users of devices with buzzers can get audible feedback about whether they have turned the GPS off or on. This is especially valuable for screenless devices such as the T1000E where it may not be immediately obvious the GPS has been disabled. --- src/buzz/buzz.cpp | 12 ++++++++++++ src/buzz/buzz.h | 2 ++ src/gps/GPS.cpp | 5 ++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/buzz/buzz.cpp b/src/buzz/buzz.cpp index e42a9c203..8db9602bc 100644 --- a/src/buzz/buzz.cpp +++ b/src/buzz/buzz.cpp @@ -55,6 +55,18 @@ void playBeep() playTones(melody, sizeof(melody) / sizeof(ToneDuration)); } +void playGPSEnableBeep() +{ + ToneDuration melody[] = {{NOTE_C3, DURATION_1_8}, {NOTE_FS3, DURATION_1_4}, {NOTE_CS4, DURATION_1_4}}; + playTones(melody, sizeof(melody) / sizeof(ToneDuration)); +} + +void playGPSDisableBeep() +{ + ToneDuration melody[] = {{NOTE_CS4, DURATION_1_8}, {NOTE_FS3, DURATION_1_4}, {NOTE_C3, DURATION_1_4}}; + playTones(melody, sizeof(melody) / sizeof(ToneDuration)); +} + void playStartMelody() { ToneDuration melody[] = {{NOTE_FS3, DURATION_1_8}, {NOTE_AS3, DURATION_1_8}, {NOTE_CS4, DURATION_1_4}}; diff --git a/src/buzz/buzz.h b/src/buzz/buzz.h index 3883bd057..c52c3020c 100644 --- a/src/buzz/buzz.h +++ b/src/buzz/buzz.h @@ -3,3 +3,5 @@ void playBeep(); void playStartMelody(); void playShutdownMelody(); +void playGPSEnableBeep(); +void playGPSDisableBeep(); \ No newline at end of file diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 18feb6daa..c33263326 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 "buzz.h" #include "meshUtils.h" #include "main.h" // pmu_found @@ -1680,6 +1681,7 @@ void GPS::toggleGpsMode() if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) { config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_DISABLED; LOG_INFO("User toggled GpsMode. Now DISABLED."); + playGPSDisableBeep(); #ifdef GNSS_AIROHA if (powerState == GPS_ACTIVE) { LOG_DEBUG("User power Off GPS"); @@ -1690,7 +1692,8 @@ void GPS::toggleGpsMode() } else if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_DISABLED) { config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED; LOG_INFO("User toggled GpsMode. Now ENABLED"); + playGPSEnableBeep(); enable(); } } -#endif // Exclude GPS \ No newline at end of file +#endif // Exclude GPS From b8b6894d589aa147abea65f8648fdebff86828b9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 18 Oct 2024 06:00:55 -0500 Subject: [PATCH 07/20] [create-pull-request] automated change (#5091) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/mesh.pb.h | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/protobufs b/protobufs index e22381a3c..0fed5c770 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit e22381a3c6bbdd428f127ed8c0aa0a37789c3907 +Subproject commit 0fed5c7709d2cec043a0f6daefa86ff11de0b946 diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 313719d9b..97bf802c1 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -778,6 +778,8 @@ typedef struct _meshtastic_MyNodeInfo { /* The minimum app version that can talk to this device. Phone/PC apps should compare this to their build number and if too low tell the user they must update their app */ uint32_t min_app_version; + /* Unique hardware identifier for this device */ + uint64_t device_id; } meshtastic_MyNodeInfo; /* Debug output from the device. @@ -1112,7 +1114,7 @@ extern "C" { #define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0} #define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0} -#define meshtastic_MyNodeInfo_init_default {0, 0, 0} +#define meshtastic_MyNodeInfo_init_default {0, 0, 0, 0} #define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN} #define meshtastic_QueueStatus_init_default {0, 0, 0, 0} #define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}} @@ -1137,7 +1139,7 @@ extern "C" { #define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0} #define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0} -#define meshtastic_MyNodeInfo_init_zero {0, 0, 0} +#define meshtastic_MyNodeInfo_init_zero {0, 0, 0, 0} #define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN} #define meshtastic_QueueStatus_init_zero {0, 0, 0, 0} #define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}} @@ -1244,6 +1246,7 @@ extern "C" { #define meshtastic_MyNodeInfo_my_node_num_tag 1 #define meshtastic_MyNodeInfo_reboot_count_tag 8 #define meshtastic_MyNodeInfo_min_app_version_tag 11 +#define meshtastic_MyNodeInfo_device_id_tag 12 #define meshtastic_LogRecord_message_tag 1 #define meshtastic_LogRecord_time_tag 2 #define meshtastic_LogRecord_source_tag 3 @@ -1446,7 +1449,8 @@ X(a, STATIC, SINGULAR, BOOL, is_favorite, 10) #define meshtastic_MyNodeInfo_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, my_node_num, 1) \ X(a, STATIC, SINGULAR, UINT32, reboot_count, 8) \ -X(a, STATIC, SINGULAR, UINT32, min_app_version, 11) +X(a, STATIC, SINGULAR, UINT32, min_app_version, 11) \ +X(a, STATIC, SINGULAR, UINT64, device_id, 12) #define meshtastic_MyNodeInfo_CALLBACK NULL #define meshtastic_MyNodeInfo_DEFAULT NULL @@ -1669,7 +1673,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_LogRecord_size 426 #define meshtastic_MeshPacket_size 367 #define meshtastic_MqttClientProxyMessage_size 501 -#define meshtastic_MyNodeInfo_size 18 +#define meshtastic_MyNodeInfo_size 29 #define meshtastic_NeighborInfo_size 258 #define meshtastic_Neighbor_size 22 #define meshtastic_NodeInfo_size 317 From dfeb33d46e25415d44a1b48e001bd742fdf3b2e9 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Fri, 18 Oct 2024 12:30:46 -0500 Subject: [PATCH 08/20] Add DIO2_AS_RF_SWITCH to pinedio prefilled config. --- bin/config-dist.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/config-dist.yaml b/bin/config-dist.yaml index 3a470b7bb..a755954b1 100644 --- a/bin/config-dist.yaml +++ b/bin/config-dist.yaml @@ -20,6 +20,7 @@ Lora: # CS: 0 # IRQ: 10 # Busy: 11 +# DIO2_AS_RF_SWITCH: true # spidev: spidev0.1 # Module: RF95 # Adafruit RFM9x @@ -154,4 +155,4 @@ Webserver: General: MaxNodes: 200 - MaxMessageQueue: 100 \ No newline at end of file + MaxMessageQueue: 100 From a27f9fcdbd48feed0ed0dd6824ba1afd6b56c0da Mon Sep 17 00:00:00 2001 From: madeofstown <33820964+madeofstown@users.noreply.github.com> Date: Fri, 18 Oct 2024 18:19:24 -0700 Subject: [PATCH 09/20] Add `-p` flag (#5093) Add the `-p` to the `mkdir` so it doesn't fail when the folder already exists Co-authored-by: Ben Meadors --- bin/native-install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/native-install.sh b/bin/native-install.sh index ba71c4f46..a8fcc29a6 100755 --- a/bin/native-install.sh +++ b/bin/native-install.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash cp "release/meshtasticd_linux_$(uname -m)" /usr/sbin/meshtasticd -mkdir /etc/meshtasticd +mkdir -p /etc/meshtasticd if [[ -f "/etc/meshtasticd/config.yaml" ]]; then cp bin/config-dist.yaml /etc/meshtasticd/config-upgrade.yaml else From 304f26b909e6e9001918342369bc9f3ccfd26439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Sat, 19 Oct 2024 19:01:58 +0200 Subject: [PATCH 10/20] Revert "Permanently engage !CTRL" --- variants/rp2040-lora/variant.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/variants/rp2040-lora/variant.h b/variants/rp2040-lora/variant.h index c93105f0e..f1826605f 100644 --- a/variants/rp2040-lora/variant.h +++ b/variants/rp2040-lora/variant.h @@ -54,7 +54,7 @@ #define SX126X_DIO1 LORA_DIO1 #define SX126X_BUSY LORA_BUSY #define SX126X_RESET LORA_RESET -#define SX126X_DIO2_AS_RF_SWITCH // Antenna switch CTRL -#define SX126X_POWER_EN LORA_DIO4 // Antenna switch !CTRL via GPIO17 +#define SX126X_DIO2_AS_RF_SWITCH // Antenna switch CTRL +#define SX126X_RXEN LORA_DIO4 // Antenna switch !CTRL via GPIO17 // #define SX126X_DIO3_TCXO_VOLTAGE 1.8 -#endif +#endif \ No newline at end of file From 4575352d8cd71ab2adf7ba105ebd27d3ecc39c61 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sat, 19 Oct 2024 12:48:00 -0500 Subject: [PATCH 11/20] Initial NODENUM_BROADCAST_NO_LORA implementation with NeighborInfo module (#5087) * Initial NODENUM_BROADCAST_NO_LORA implementation with NeighborInfo module * isBroadcast * Trunkt --- src/mesh/FloodingRouter.cpp | 2 +- src/mesh/MeshModule.cpp | 2 +- src/mesh/MeshTypes.h | 4 +++- src/mesh/NodeDB.cpp | 5 +++++ src/mesh/RadioLibInterface.cpp | 5 ++++- src/mesh/Router.cpp | 10 +++++----- src/modules/NeighborInfoModule.cpp | 2 +- src/modules/NodeInfoModule.cpp | 2 +- src/modules/RoutingModule.cpp | 5 ++--- 9 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index 268fee2b0..6760d70eb 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -44,7 +44,7 @@ bool FloodingRouter::isRebroadcaster() void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c) { bool isAckorReply = (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) && (p->decoded.request_id != 0); - if (isAckorReply && !isToUs(p) && p->to != NODENUM_BROADCAST) { + if (isAckorReply && !isToUs(p) && !isBroadcast(p->to)) { // do not flood direct message that is ACKed or replied to LOG_DEBUG("Rxd an ACK/reply not for me, cancel rebroadcast."); Router::cancelSending(p->to, p->decoded.request_id); // cancel rebroadcast for this DM diff --git a/src/mesh/MeshModule.cpp b/src/mesh/MeshModule.cpp index 48c3ee47d..a8de540eb 100644 --- a/src/mesh/MeshModule.cpp +++ b/src/mesh/MeshModule.cpp @@ -86,7 +86,7 @@ void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src) // Was this message directed to us specifically? Will be false if we are sniffing someone elses packets auto ourNodeNum = nodeDB->getNodeNum(); - bool toUs = mp.to == NODENUM_BROADCAST || isToUs(&mp); + bool toUs = isBroadcast(mp.to) || isToUs(&mp); for (auto i = modules->begin(); i != modules->end(); ++i) { auto &pi = **i; diff --git a/src/mesh/MeshTypes.h b/src/mesh/MeshTypes.h index 27d100fbe..7a3d785dd 100644 --- a/src/mesh/MeshTypes.h +++ b/src/mesh/MeshTypes.h @@ -57,4 +57,6 @@ bool isFromUs(const meshtastic_MeshPacket *p); bool isToUs(const meshtastic_MeshPacket *p); /* Some clients might not properly set priority, therefore we fix it here. */ -void fixPriority(meshtastic_MeshPacket *p); \ No newline at end of file +void fixPriority(meshtastic_MeshPacket *p); + +bool isBroadcast(uint32_t dest); \ No newline at end of file diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index ebe3debdb..78ccdd85a 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -222,6 +222,11 @@ bool isToUs(const meshtastic_MeshPacket *p) return p->to == nodeDB->getNodeNum(); } +bool isBroadcast(uint32_t dest) +{ + return dest == NODENUM_BROADCAST || dest == NODENUM_BROADCAST_NO_LORA; +} + bool NodeDB::resetRadioConfig(bool factory_reset) { bool didFactoryReset = false; diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index 1ec3b9077..f44d50d36 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -467,7 +467,10 @@ void RadioLibInterface::setStandby() void RadioLibInterface::startSend(meshtastic_MeshPacket *txp) { printPacket("Starting low level send", txp); - if (disabled || !config.lora.tx_enabled) { + if (txp->to == NODENUM_BROADCAST_NO_LORA) { + LOG_DEBUG("Drop Tx packet because dest is broadcast no-lora"); + packetPool.release(txp); + } else if (disabled || !config.lora.tx_enabled) { LOG_WARN("Drop Tx packet because LoRa Tx disabled"); packetPool.release(txp); } else { diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index b7296f959..84ae7bbb0 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -181,7 +181,7 @@ ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src) } else { // If we are sending a broadcast, we also treat it as if we just received it ourself // this allows local apps (and PCs) to see broadcasts sourced locally - if (p->to == NODENUM_BROADCAST) { + if (isBroadcast(p->to)) { handleReceived(p, src); } @@ -240,7 +240,7 @@ ErrorCode Router::send(meshtastic_MeshPacket *p) // assert // Never set the want_ack flag on broadcast packets sent over the air. - if (p->to == NODENUM_BROADCAST) + if (isBroadcast(p->to)) p->want_ack = false; // Up until this point we might have been using 0 for the from address (if it started with the phone), but when we send over @@ -328,7 +328,7 @@ bool perhapsDecode(meshtastic_MeshPacket *p) memcpy(ScratchEncrypted, p->encrypted.bytes, rawSize); #if !(MESHTASTIC_EXCLUDE_PKI) // Attempt PKI decryption first - if (p->channel == 0 && isToUs(p) && p->to > 0 && p->to != NODENUM_BROADCAST && nodeDB->getMeshNode(p->from) != nullptr && + if (p->channel == 0 && isToUs(p) && p->to > 0 && !isBroadcast(p->to) && nodeDB->getMeshNode(p->from) != nullptr && nodeDB->getMeshNode(p->from)->user.public_key.size > 0 && nodeDB->getMeshNode(p->to)->user.public_key.size > 0 && rawSize > MESHTASTIC_PKC_OVERHEAD) { LOG_DEBUG("Attempting PKI decryption"); @@ -493,7 +493,7 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p) // Don't use PKC if it's not explicitly requested and a non-primary channel is requested !(p->pki_encrypted != true && p->channel > 0) && // Check for valid keys and single node destination - config.security.private_key.size == 32 && p->to != NODENUM_BROADCAST && node != nullptr && + config.security.private_key.size == 32 && !isBroadcast(p->to) && node != nullptr && // Check for a known public key for the destination (node->user.public_key.size == 32) && // Some portnums either make no sense to send with PKC @@ -615,7 +615,7 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src) #if !MESHTASTIC_EXCLUDE_MQTT // Mark as pki_encrypted if it is not yet decoded and MQTT encryption is also enabled, hash matches and it's a DM not to // us (because we would be able to decrypt it) - if (!decoded && moduleConfig.mqtt.encryption_enabled && p->channel == 0x00 && p->to != NODENUM_BROADCAST && !isToUs(p)) + if (!decoded && moduleConfig.mqtt.encryption_enabled && p->channel == 0x00 && !isBroadcast(p->to) && !isToUs(p)) p_encrypted->pki_encrypted = true; // After potentially altering it, publish received message to MQTT if we're not the original transmitter of the packet if ((decoded || p_encrypted->pki_encrypted) && moduleConfig.mqtt.enabled && !isFromUs(p) && mqtt) diff --git a/src/modules/NeighborInfoModule.cpp b/src/modules/NeighborInfoModule.cpp index 85552a6bf..cbf63e9af 100644 --- a/src/modules/NeighborInfoModule.cpp +++ b/src/modules/NeighborInfoModule.cpp @@ -122,7 +122,7 @@ Will be used for broadcast. int32_t NeighborInfoModule::runOnce() { if (airTime->isTxAllowedChannelUtil(true) && airTime->isTxAllowedAirUtil()) { - sendNeighborInfo(NODENUM_BROADCAST, false); + sendNeighborInfo(NODENUM_BROADCAST_NO_LORA, false); } return Default::getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_neighbor_info_broadcast_secs); } diff --git a/src/modules/NodeInfoModule.cpp b/src/modules/NodeInfoModule.cpp index 89f6ed3c4..843711807 100644 --- a/src/modules/NodeInfoModule.cpp +++ b/src/modules/NodeInfoModule.cpp @@ -16,7 +16,7 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes bool hasChanged = nodeDB->updateUser(getFrom(&mp), p, mp.channel); - bool wasBroadcast = mp.to == NODENUM_BROADCAST; + bool wasBroadcast = isBroadcast(mp.to); // Show new nodes on LCD screen if (wasBroadcast) { diff --git a/src/modules/RoutingModule.cpp b/src/modules/RoutingModule.cpp index 3b7be1ab7..f0d007d9d 100644 --- a/src/modules/RoutingModule.cpp +++ b/src/modules/RoutingModule.cpp @@ -13,8 +13,7 @@ bool RoutingModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mesh printPacket("Routing sniffing", &mp); router->sniffReceived(&mp, r); - bool maybePKI = - mp.which_payload_variant == meshtastic_MeshPacket_encrypted_tag && mp.channel == 0 && mp.to != NODENUM_BROADCAST; + bool maybePKI = mp.which_payload_variant == meshtastic_MeshPacket_encrypted_tag && mp.channel == 0 && !isBroadcast(mp.to); // Beginning of logic whether to drop the packet based on Rebroadcast mode if (mp.which_payload_variant == meshtastic_MeshPacket_encrypted_tag && (config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY || @@ -28,7 +27,7 @@ bool RoutingModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mesh // FIXME - move this to a non promsicious PhoneAPI module? // Note: we are careful not to send back packets that started with the phone back to the phone - if ((mp.to == NODENUM_BROADCAST || isToUs(&mp)) && (mp.from != 0)) { + if ((isBroadcast(mp.to) || isToUs(&mp)) && (mp.from != 0)) { printPacket("Delivering rx packet", &mp); service->handleFromRadio(&mp); } From 7e3931b05da532f0af24cd3d487ef0bf7be75b17 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sat, 19 Oct 2024 20:05:52 -0500 Subject: [PATCH 12/20] Move 115200 baud GNSS probe earlier (#5101) * Move 115200 baud GNSS probe earlier * Even more optimized! --- src/gps/GPS.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gps/GPS.h b/src/gps/GPS.h index bc95613b3..8b1982cf7 100644 --- a/src/gps/GPS.h +++ b/src/gps/GPS.h @@ -75,7 +75,7 @@ class GPS : private concurrency::OSThread uint8_t fixType = 0; // fix type from GPGSA #endif private: - const int serialSpeeds[6] = {9600, 4800, 38400, 57600, 115200, 9600}; + const int serialSpeeds[6] = {9600, 115200, 38400, 4800, 57600, 9600}; uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastFixStartMsec = 0; uint32_t rx_gpio = 0; uint32_t tx_gpio = 0; From 2ba72c154ac6078c8884f705df594d776c254e6a Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Sun, 20 Oct 2024 20:46:25 +1100 Subject: [PATCH 13/20] Fix GPS_DEBUG output (#5100) After the recent change to move logging line breaks to a central location, GPS_DEBUG is now emitting one character per line, making the logs unusable. Patch uses local strings and appends to collate and then print in the right places. Fixes https://github.com/meshtastic/firmware/issues/5099 Co-authored-by: Ben Meadors --- src/gps/GPS.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index c33263326..3a9516c84 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -267,6 +267,9 @@ GPS_RESPONSE GPS::getACK(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis) uint32_t startTime = millis(); const char frame_errors[] = "More than 100 frame errors"; int sCounter = 0; +#ifdef GPS_DEBUG + std::string debugmsg = ""; +#endif for (int j = 2; j < 6; j++) { buf[8] += buf[j]; @@ -292,20 +295,24 @@ GPS_RESPONSE GPS::getACK(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis) if (b == frame_errors[sCounter]) { sCounter++; if (sCounter == 26) { +#ifdef GPS_DEBUG + + LOG_DEBUG(debugmsg.c_str()); +#endif return GNSS_RESPONSE_FRAME_ERRORS; } } else { sCounter = 0; } #ifdef GPS_DEBUG - LOG_DEBUG("%02X", b); + debugmsg += vformat("%02X", b); #endif if (b == buf[ack]) { ack++; } else { if (ack == 3 && b == 0x00) { // UBX-ACK-NAK message #ifdef GPS_DEBUG - LOG_DEBUG(""); + LOG_DEBUG(debugmsg.c_str()); #endif LOG_WARN("Got NAK for class %02X message %02X", class_id, msg_id); return GNSS_RESPONSE_NAK; // NAK received @@ -315,7 +322,7 @@ GPS_RESPONSE GPS::getACK(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis) } } #ifdef GPS_DEBUG - LOG_DEBUG(""); + LOG_DEBUG(debugmsg.c_str()); LOG_WARN("No response for class %02X message %02X", class_id, msg_id); #endif return GNSS_RESPONSE_NONE; // No response received within timeout @@ -1624,6 +1631,9 @@ bool GPS::whileActive() { unsigned int charsInBuf = 0; bool isValid = false; +#ifdef GPS_DEBUG + std::string debugmsg = ""; +#endif if (powerState != GPS_ACTIVE) { clearBuffer(); return false; @@ -1641,7 +1651,7 @@ bool GPS::whileActive() int c = _serial_gps->read(); UBXscratch[charsInBuf] = c; #ifdef GPS_DEBUG - LOG_DEBUG("%c", c); + debugmsg += vformat("%c", (c >= 32 && c <= 126) ? c : '.'); #endif isValid |= reader.encode(c); if (charsInBuf > sizeof(UBXscratch) - 10 || c == '\r') { @@ -1653,6 +1663,9 @@ bool GPS::whileActive() charsInBuf++; } } +#ifdef GPS_DEBUG + LOG_DEBUG(debugmsg.c_str()); +#endif return isValid; } void GPS::enable() @@ -1696,4 +1709,4 @@ void GPS::toggleGpsMode() enable(); } } -#endif // Exclude GPS +#endif // Exclude GPS \ No newline at end of file From 18ca5b44499f339457011e5900d08a8c0c9fb83c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Sun, 20 Oct 2024 21:54:07 +0200 Subject: [PATCH 14/20] Wide_Lora uses 12 symbols to be compatible with SX1280 --- src/mesh/LR11x0Interface.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mesh/LR11x0Interface.cpp b/src/mesh/LR11x0Interface.cpp index dd6d97317..d0c1a1fbc 100644 --- a/src/mesh/LR11x0Interface.cpp +++ b/src/mesh/LR11x0Interface.cpp @@ -67,8 +67,10 @@ template bool LR11x0Interface::init() power = LR1110_MAX_POWER; if ((power > LR1120_MAX_POWER) && - (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) // clamp again if wide freq range + (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) { // clamp again if wide freq range power = LR1120_MAX_POWER; + preambleLength = 12; // 12 is the default for operation above 2GHz + } limitPower(); From 09c8642aa64c776d925414a46ee7f7c49b4093ba Mon Sep 17 00:00:00 2001 From: GUVWAF <78759985+GUVWAF@users.noreply.github.com> Date: Mon, 21 Oct 2024 00:04:45 +0200 Subject: [PATCH 15/20] Fix rebroadcasting encrypted packets when `KNOWN_ONLY` or `LOCAL_ONLY` is used (#5109) --- src/modules/RoutingModule.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/RoutingModule.cpp b/src/modules/RoutingModule.cpp index f0d007d9d..f11a9a542 100644 --- a/src/modules/RoutingModule.cpp +++ b/src/modules/RoutingModule.cpp @@ -10,9 +10,6 @@ RoutingModule *routingModule; bool RoutingModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Routing *r) { - printPacket("Routing sniffing", &mp); - router->sniffReceived(&mp, r); - bool maybePKI = mp.which_payload_variant == meshtastic_MeshPacket_encrypted_tag && mp.channel == 0 && !isBroadcast(mp.to); // Beginning of logic whether to drop the packet based on Rebroadcast mode if (mp.which_payload_variant == meshtastic_MeshPacket_encrypted_tag && @@ -25,6 +22,9 @@ bool RoutingModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mesh return false; } + printPacket("Routing sniffing", &mp); + router->sniffReceived(&mp, r); + // FIXME - move this to a non promsicious PhoneAPI module? // Note: we are careful not to send back packets that started with the phone back to the phone if ((isBroadcast(mp.to) || isToUs(&mp)) && (mp.from != 0)) { From 5ff8c904c8ef9d33111bbe6856a50b5bf4359e7c Mon Sep 17 00:00:00 2001 From: aussieklutz Date: Mon, 21 Oct 2024 16:53:36 +1000 Subject: [PATCH 16/20] MPR121 Touch IC Based Keypad Input Module (#5103) Implements an input driver utilising the MPR121 Touch IC and is compatible with common MPR121 keypad PCB's. - Implements a "candybar" phone style 12-key keypad - multiple taps to rotate through the character set - longpress for navigation keys - keymap to allow arbitrary routing of MPR121 pin to button configuration - extendable to other key functions - Integrates with the existing kbI2cBase implementation - Works with CannedMessageModule Freetext mode - Can be used with common MPR121 boards, such as https://www.amazon.com/MPR121-Capacitive-Keyboard-Buttons-Sensitive/dp/B083R89CHB/ref=sr_1_6 - Of use for PCB based radios, where some form of low surface area low component freetext input is required, but also without consuming too many IO pins. - Tested on a T3S3 connected to Wire1 (Second) interface. - Demonstration of functionality: https://youtu.be/UI6QP6nGvhY --- src/configuration.h | 1 + src/detect/ScanI2C.cpp | 4 +- src/detect/ScanI2C.h | 3 +- src/detect/ScanI2CTwoWire.cpp | 13 +- src/input/MPR121Keyboard.cpp | 430 ++++++++++++++++++++++++++++++++++ src/input/MPR121Keyboard.h | 56 +++++ src/input/cardKbI2cImpl.cpp | 9 +- src/input/kbI2cBase.cpp | 69 ++++++ src/input/kbI2cBase.h | 4 +- src/main.cpp | 4 + 10 files changed, 586 insertions(+), 7 deletions(-) create mode 100644 src/input/MPR121Keyboard.cpp create mode 100644 src/input/MPR121Keyboard.h diff --git a/src/configuration.h b/src/configuration.h index 10a4e0a99..66070eb40 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -114,6 +114,7 @@ along with this program. If not, see . #define CARDKB_ADDR 0x5F #define TDECK_KB_ADDR 0x55 #define BBQ10_KB_ADDR 0x1F +#define MPR121_KB_ADDR 0x5A // ----------------------------------------------------------------------------- // SENSOR diff --git a/src/detect/ScanI2C.cpp b/src/detect/ScanI2C.cpp index a9d70edaa..41ba8257e 100644 --- a/src/detect/ScanI2C.cpp +++ b/src/detect/ScanI2C.cpp @@ -31,8 +31,8 @@ ScanI2C::FoundDevice ScanI2C::firstRTC() const ScanI2C::FoundDevice ScanI2C::firstKeyboard() const { - ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004}; - return firstOfOrNONE(4, types); + ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004, MPR121KB}; + return firstOfOrNONE(5, types); } ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index 07db3fd57..b2c482c98 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -61,7 +61,8 @@ class ScanI2C STK8BAXX, ICM20948, MAX30102, - TPS65233 + TPS65233, + MPR121KB } DeviceType; // typedef uint8_t DeviceAddress; diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index 0401a5ecc..71e475904 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -243,6 +243,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard found"); SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10 keyboard found"); + SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found"); #ifdef HAS_NCP5623 SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623 RGB LED found"); @@ -408,7 +409,17 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) #ifdef HAS_TPS65233 SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233 BIAS-T found"); #endif - SCAN_SIMPLE_CASE(MLX90614_ADDR_DEF, MLX90614, "MLX90614 IR temp sensor found"); + + case MLX90614_ADDR_DEF: + registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0e), 1); + if (registerValue == 0x5a) { + type = MLX90614; + LOG_INFO("MLX90614 IR temp sensor found"); + } else { + type = MPR121KB; + LOG_INFO("MPR121KB keyboard found"); + } + break; case ICM20948_ADDR: // same as BMX160_ADDR case ICM20948_ADDR_ALT: // same as MPU6050_ADDR diff --git a/src/input/MPR121Keyboard.cpp b/src/input/MPR121Keyboard.cpp new file mode 100644 index 000000000..e1b32aa54 --- /dev/null +++ b/src/input/MPR121Keyboard.cpp @@ -0,0 +1,430 @@ +// Based on the BBQ10 Keyboard + +#include "MPR121Keyboard.h" +#include "configuration.h" +#include + +#define _MPR121_REG_KEY 0x5a + +#define _MPR121_REG_TOUCH_STATUS 0x00 +#define _MPR121_REG_ELECTRODE_FILTERED_DATA +#define _MPR121_REG_BASELINE_VALUE 0x1E + +// Baseline filters +#define _MPR121_REG_MAX_HALF_DELTA_RISING 0x2B +#define _MPR121_REG_NOISE_HALF_DELTA_RISING 0x2C +#define _MPR121_REG_NOISE_COUNT_LIMIT_RISING 0x2D +#define _MPR121_REG_FILTER_DELAY_COUNT_RISING 0x2E +#define _MPR121_REG_MAX_HALF_DELTA_FALLING 0x2F +#define _MPR121_REG_NOISE_HALF_DELTA_FALLING 0x30 +#define _MPR121_REG_NOISE_COUNT_LIMIT_FALLING 0x31 +#define _MPR121_REG_FILTER_DELAY_COUNT_FALLING 0x32 +#define _MPR121_REG_NOISE_HALF_DELTA_TOUCHED 0x33 +#define _MPR121_REG_NOISE_COUNT_LIMIT_TOUCHED 0x34 +#define _MPR121_REG_FILTER_DELAY_COUNT_TOUCHED 0x35 + +#define _MPR121_REG_TOUCH_THRESHOLD 0x41 // First input, +2 for subsequent +#define _MPR121_REG_RELEASE_THRESHOLD 0x42 // First input, +2 for subsequent +#define _MPR121_REG_DEBOUNCE 0x5B +#define _MPR121_REG_CONFIG1 0x5C +#define _MPR121_REG_CONFIG2 0x5D +#define _MPR121_REG_ELECTRODE_CONFIG 0x5E +#define _MPR121_REG_SOFT_RESET 0x80 + +#define _KEY_MASK 0x0FFF // Key mask for the first 12 bits +#define _NUM_KEYS 12 + +#define ECR_CALIBRATION_TRACK_FROM_ZERO (0 << 6) +#define ECR_CALIBRATION_LOCK (1 << 6) +#define ECR_CALIBRATION_TRACK_FROM_PARTIAL_FILTER (2 << 6) // Recommended Typical Mode +#define ECR_CALIBRATION_TRACK_FROM_FULL_FILTER (3 << 6) +#define ECR_PROXIMITY_DETECTION_OFF (0 << 0) // Not using proximity detection +#define ECR_TOUCH_DETECTION_12CH (12 << 0) // Using all 12 channels + +#define MPR121_NONE 0x00 +#define MPR121_REBOOT 0x90 +#define MPR121_LEFT 0xb4 +#define MPR121_UP 0xb5 +#define MPR121_DOWN 0xb6 +#define MPR121_RIGHT 0xb7 +#define MPR121_ESC 0x1b +#define MPR121_BSP 0x08 +#define MPR121_SELECT 0x0d + +#define MPR121_FN_ON 0xf1 +#define MPR121_FN_OFF 0xf2 + +#define LONG_PRESS_THRESHOLD 2000 +#define MULTI_TAP_THRESHOLD 2000 + +uint8_t TapMod[12] = {1, 2, 1, 13, 7, 7, 7, 7, 7, 9, 7, 9}; // Num chars per key, Modulus for rotating through characters + +unsigned char MPR121_TapMap[12][13] = {{MPR121_BSP}, + {'0', ' '}, + {MPR121_SELECT}, + {'1', '.', ',', '?', '!', ':', ';', '-', '_', '\\', '/', '(', ')'}, + {'2', 'a', 'b', 'c', 'A', 'B', 'C'}, + {'3', 'd', 'e', 'f', 'D', 'E', 'F'}, + {'4', 'g', 'h', 'i', 'G', 'H', 'I'}, + {'5', 'j', 'k', 'l', 'J', 'K', 'L'}, + {'6', 'm', 'n', 'o', 'M', 'N', 'O'}, + {'7', 'p', 'q', 'r', 's', 'P', 'Q', 'R', 'S'}, + {'8', 't', 'u', 'v', 'T', 'U', 'V'}, + {'9', 'w', 'x', 'y', 'z', 'W', 'X', 'Y', 'Z'}}; + +unsigned char MPR121_LongPressMap[12] = {MPR121_ESC, ' ', MPR121_NONE, MPR121_NONE, MPR121_UP, MPR121_NONE, + MPR121_LEFT, MPR121_NONE, MPR121_RIGHT, MPR121_NONE, MPR121_DOWN, MPR121_NONE}; + +// Translation map from left to right, top to bottom layout to a more convenient layout to manufacture, matching the +// https://www.amazon.com.au/Capacitive-Sensitive-Sensitivity-Replacement-Traditional/dp/B0CTJD5KW9/ref=pd_ci_mcx_mh_mcx_views_0_title?th=1 +/*uint8_t MPR121_KeyMap[12] = { + 9, 6, 3, 0, + 10, 7, 4, 1, + 11, 8, 5, 2 +};*/ +// Rotated Layout +uint8_t MPR121_KeyMap[12] = {2, 5, 8, 11, 1, 4, 7, 10, 0, 3, 6, 9}; + +MPR121Keyboard::MPR121Keyboard() : m_wire(nullptr), m_addr(0), readCallback(nullptr), writeCallback(nullptr) +{ + // LOG_DEBUG("MPR121 @ %02x\n", m_addr); + state = Init; + last_key = -1; + last_tap = 0L; + char_idx = 0; + queue = ""; +} + +void MPR121Keyboard::begin(uint8_t addr, TwoWire *wire) +{ + m_addr = addr; + m_wire = wire; + + m_wire->begin(); + + reset(); +} + +void MPR121Keyboard::begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr) +{ + m_addr = addr; + m_wire = nullptr; + writeCallback = w; + readCallback = r; + reset(); +} + +void MPR121Keyboard::reset() +{ + LOG_DEBUG("MPR121 Resetting..."); + // Trigger a MPR121 Soft Reset + if (m_wire) { + m_wire->beginTransmission(m_addr); + m_wire->write(_MPR121_REG_SOFT_RESET); + m_wire->endTransmission(); + } + if (writeCallback) { + uint8_t data = 0; + writeCallback(m_addr, _MPR121_REG_SOFT_RESET, &data, 0); + } + delay(100); + // Reset Electrode Configuration to 0x00, Stop Mode + writeRegister(_MPR121_REG_ELECTRODE_CONFIG, 0x00); + delay(100); + + LOG_DEBUG("MPR121 Configuring"); + // Set touch release thresholds + for (uint8_t i = 0; i < 12; i++) { + // Set touch threshold + writeRegister(_MPR121_REG_TOUCH_THRESHOLD + (i * 2), 15); + delay(20); + // Set release threshold + writeRegister(_MPR121_REG_RELEASE_THRESHOLD + (i * 2), 7); + delay(20); + } + // Configure filtering and baseline registers + writeRegister(_MPR121_REG_MAX_HALF_DELTA_RISING, 0x01); + delay(20); + writeRegister(_MPR121_REG_MAX_HALF_DELTA_FALLING, 0x01); + delay(20); + writeRegister(_MPR121_REG_NOISE_HALF_DELTA_RISING, 0x01); + delay(20); + writeRegister(_MPR121_REG_NOISE_HALF_DELTA_FALLING, 0x05); + delay(20); + writeRegister(_MPR121_REG_NOISE_HALF_DELTA_TOUCHED, 0x00); + delay(20); + writeRegister(_MPR121_REG_NOISE_COUNT_LIMIT_RISING, 0x0e); + delay(20); + writeRegister(_MPR121_REG_NOISE_COUNT_LIMIT_FALLING, 0x01); + delay(20); + writeRegister(_MPR121_REG_NOISE_COUNT_LIMIT_TOUCHED, 0x00); + delay(20); + writeRegister(_MPR121_REG_FILTER_DELAY_COUNT_RISING, 0x00); + delay(20); + writeRegister(_MPR121_REG_FILTER_DELAY_COUNT_FALLING, 0x00); + delay(20); + writeRegister(_MPR121_REG_FILTER_DELAY_COUNT_TOUCHED, 0x00); + delay(20); + // Set Debounce to 0x02 + writeRegister(_MPR121_REG_DEBOUNCE, 0x00); + delay(20); + // Set Filter1 itterations and discharge current 6x and 16uA respectively (0x10) + writeRegister(_MPR121_REG_CONFIG1, 0x10); + delay(20); + // Set CDT to 0.5us, Filter2 itterations to 4x, and Sample interval = 0 (0x20) + writeRegister(_MPR121_REG_CONFIG2, 0x20); + delay(20); + // Enter run mode by Seting partial filter calibration tracking, disable proximity detection, enable 12 channels + writeRegister(_MPR121_REG_ELECTRODE_CONFIG, + ECR_CALIBRATION_TRACK_FROM_PARTIAL_FILTER | ECR_PROXIMITY_DETECTION_OFF | ECR_TOUCH_DETECTION_12CH); + delay(100); + LOG_DEBUG("MPR121 Running"); + state = Idle; +} + +void MPR121Keyboard::attachInterrupt(uint8_t pin, void (*func)(void)) const +{ + pinMode(pin, INPUT_PULLUP); + ::attachInterrupt(digitalPinToInterrupt(pin), func, RISING); +} + +void MPR121Keyboard::detachInterrupt(uint8_t pin) const +{ + ::detachInterrupt(pin); +} + +uint8_t MPR121Keyboard::status() const +{ + return readRegister16(_MPR121_REG_KEY); +} + +uint8_t MPR121Keyboard::keyCount() const +{ + // Read the key register + uint16_t keyRegister = readRegister16(_MPR121_REG_KEY); + return keyCount(keyRegister); +} + +uint8_t MPR121Keyboard::keyCount(uint16_t value) const +{ + // Mask the first 12 bits + uint16_t buttonState = value & _KEY_MASK; + + // Count how many bits are set to 1 (i.e., how many buttons are pressed) + uint8_t numButtonsPressed = 0; + for (uint8_t i = 0; i < 12; ++i) { + if (buttonState & (1 << i)) { + numButtonsPressed++; + } + } + + return numButtonsPressed; +} + +bool MPR121Keyboard::hasEvent() +{ + return queue.length() > 0; +} + +void MPR121Keyboard::queueEvent(char next) +{ + if (next == MPR121_NONE) { + return; + } + queue.concat(next); +} + +char MPR121Keyboard::dequeueEvent() +{ + if (queue.length() < 1) { + return MPR121_NONE; + } + char next = queue.charAt(0); + queue.remove(0, 1); + return next; +} + +void MPR121Keyboard::trigger() +{ + // Intended to fire in response to an interrupt from the MPR121 or a longpress callback + // Only functional if not in Init state + if (state != Init) { + // Read the key register + uint16_t keyRegister = readRegister16(_MPR121_REG_KEY); + uint8_t keysPressed = keyCount(keyRegister); + if (keysPressed == 0) { + // No buttons pressed + if (state == Held) + released(); + state = Idle; + return; + } + if (keysPressed == 1) { + // No buttons pressed + if (state == Held || state == HeldLong) + held(keyRegister); + if (state == Idle) + pressed(keyRegister); + return; + } + if (keysPressed > 1) { + // Multipress + state = Busy; + return; + } + } else { + reset(); + } +} + +void MPR121Keyboard::pressed(uint16_t keyRegister) +{ + if (state == Init || state == Busy) { + return; + } + if (keyCount(keyRegister) != 1) { + LOG_DEBUG("Multipress"); + return; + } else { + LOG_DEBUG("Pressed"); + } + uint16_t buttonState = keyRegister & _KEY_MASK; + uint8_t next_pin = 0; + for (uint8_t i = 0; i < 12; ++i) { + if (buttonState & (1 << i)) { + next_pin = i; + } + } + uint8_t next_key = MPR121_KeyMap[next_pin]; + LOG_DEBUG("MPR121 Pin: %i Key: %i", next_pin, next_key); + uint32_t now = millis(); + int32_t tap_interval = now - last_tap; + if (tap_interval < 0) { + // long running, millis has overflowed. + last_tap = 0; + state = Busy; + return; + } + if (next_key != last_key || tap_interval > MULTI_TAP_THRESHOLD) { + char_idx = 0; + } else { + char_idx += 1; + } + last_key = next_key; + last_tap = now; + state = Held; + return; +} + +void MPR121Keyboard::held(uint16_t keyRegister) +{ + if (state == Init || state == Busy) { + return; + } + if (keyCount(keyRegister) != 1) { + return; + } + LOG_DEBUG("Held"); + uint16_t buttonState = keyRegister & _KEY_MASK; + uint8_t next_key = 0; + for (uint8_t i = 0; i < 12; ++i) { + if (buttonState & (1 << i)) { + next_key = MPR121_KeyMap[i]; + } + } + uint32_t now = millis(); + int32_t held_interval = now - last_tap; + if (held_interval < 0 || next_key != last_key) { + // long running, millis has overflowed, or a key has been switched quickly... + last_tap = 0; + state = Busy; + return; + } + if (held_interval > LONG_PRESS_THRESHOLD) { + // Set state to heldlong, send a longpress, and reset the timer... + state = HeldLong; // heldlong will allow this function to still fire, but prevent a "release" + queueEvent(MPR121_LongPressMap[last_key]); + last_tap = now; + LOG_DEBUG("Long Press Key: %i Map: %i", last_key, MPR121_LongPressMap[last_key]); + } + return; +} + +void MPR121Keyboard::released() +{ + if (state != Held) { + return; + } + // would clear longpress callback... later. + if (last_key < 0 || last_key > _NUM_KEYS) { // reset to idle if last_key out of bounds + last_key = -1; + state = Idle; + return; + } + LOG_DEBUG("Released"); + if (char_idx > 0 && TapMod[last_key] > 1) { + queueEvent(MPR121_BSP); + LOG_DEBUG("Multi Press, Backspace"); + } + queueEvent(MPR121_TapMap[last_key][(char_idx % TapMod[last_key])]); + LOG_DEBUG("Key Press: %i Index:%i if %i Map: %i", last_key, char_idx, TapMod[last_key], + MPR121_TapMap[last_key][(char_idx % TapMod[last_key])]); +} + +uint8_t MPR121Keyboard::readRegister8(uint8_t reg) const +{ + if (m_wire) { + m_wire->beginTransmission(m_addr); + m_wire->write(reg); + m_wire->endTransmission(); + + m_wire->requestFrom(m_addr, (uint8_t)1); + if (m_wire->available() < 1) + return 0; + + return m_wire->read(); + } + if (readCallback) { + uint8_t data; + readCallback(m_addr, reg, &data, 1); + return data; + } + return 0; +} + +uint16_t MPR121Keyboard::readRegister16(uint8_t reg) const +{ + uint8_t data[2] = {0}; + // uint8_t low = 0, high = 0; + if (m_wire) { + m_wire->beginTransmission(m_addr); + m_wire->write(reg); + m_wire->endTransmission(); + + m_wire->requestFrom(m_addr, (uint8_t)2); + if (m_wire->available() < 2) + return 0; + data[0] = m_wire->read(); + data[1] = m_wire->read(); + } + if (readCallback) { + readCallback(m_addr, reg, data, 2); + } + return (data[1] << 8) | data[0]; +} + +void MPR121Keyboard::writeRegister(uint8_t reg, uint8_t value) +{ + uint8_t data[2]; + data[0] = reg; + data[1] = value; + + if (m_wire) { + m_wire->beginTransmission(m_addr); + m_wire->write(data, sizeof(uint8_t) * 2); + m_wire->endTransmission(); + } + if (writeCallback) { + writeCallback(m_addr, data[0], &(data[1]), 1); + } +} diff --git a/src/input/MPR121Keyboard.h b/src/input/MPR121Keyboard.h new file mode 100644 index 000000000..6349750ce --- /dev/null +++ b/src/input/MPR121Keyboard.h @@ -0,0 +1,56 @@ +// Based on the BBQ10 Keyboard + +#include "concurrency/NotifiedWorkerThread.h" +#include "configuration.h" +#include +#include + +class MPR121Keyboard +{ + public: + typedef uint8_t (*i2c_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len); + + enum MPR121States { Init = 0, Idle, Held, HeldLong, Busy }; + + MPR121States state; + + int8_t last_key; + uint32_t last_tap; + uint8_t char_idx; + + String queue; + + MPR121Keyboard(); + + void begin(uint8_t addr = MPR121_KB_ADDR, TwoWire *wire = &Wire); + + void begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr = MPR121_KB_ADDR); + + void reset(void); + + void attachInterrupt(uint8_t pin, void (*func)(void)) const; + void detachInterrupt(uint8_t pin) const; + + void trigger(void); + void pressed(uint16_t value); + void held(uint16_t value); + void released(void); + + uint8_t status(void) const; + uint8_t keyCount(void) const; + uint8_t keyCount(uint16_t value) const; + + bool hasEvent(void); + char dequeueEvent(void); + void queueEvent(char); + + uint8_t readRegister8(uint8_t reg) const; + uint16_t readRegister16(uint8_t reg) const; + void writeRegister(uint8_t reg, uint8_t value); + + private: + TwoWire *m_wire; + uint8_t m_addr; + i2c_com_fptr_t readCallback; + i2c_com_fptr_t writeCallback; +}; \ No newline at end of file diff --git a/src/input/cardKbI2cImpl.cpp b/src/input/cardKbI2cImpl.cpp index 59ae16866..7ad2eb2ac 100644 --- a/src/input/cardKbI2cImpl.cpp +++ b/src/input/cardKbI2cImpl.cpp @@ -12,8 +12,8 @@ void CardKbI2cImpl::init() #if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) if (cardkb_found.address == 0x00) { LOG_DEBUG("Rescanning for I2C keyboard"); - uint8_t i2caddr_scan[] = {CARDKB_ADDR, TDECK_KB_ADDR, BBQ10_KB_ADDR}; - uint8_t i2caddr_asize = 3; + uint8_t i2caddr_scan[] = {CARDKB_ADDR, TDECK_KB_ADDR, BBQ10_KB_ADDR, MPR121_KB_ADDR}; + uint8_t i2caddr_asize = 4; auto i2cScanner = std::unique_ptr(new ScanI2CTwoWire()); #if WIRE_INTERFACES_COUNT == 2 @@ -39,12 +39,17 @@ void CardKbI2cImpl::init() // assign an arbitrary value to distinguish from other models kb_model = 0x11; break; + case ScanI2C::DeviceType::MPR121KB: + // assign an arbitrary value to distinguish from other models + kb_model = 0x37; + break; default: // use this as default since it's also just zero LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00", kb_info.type); kb_model = 0x00; } } + LOG_DEBUG("Keyboard Type: 0x%02x Model: 0x%02x Address: 0x%02x\n", kb_info.type, kb_model, cardkb_found.address); if (cardkb_found.address == 0x00) { disable(); return; diff --git a/src/input/kbI2cBase.cpp b/src/input/kbI2cBase.cpp index 30188bb92..d0f36c386 100644 --- a/src/input/kbI2cBase.cpp +++ b/src/input/kbI2cBase.cpp @@ -40,6 +40,9 @@ int32_t KbI2cBase::runOnce() Q10keyboard.begin(BBQ10_KB_ADDR, &Wire1); Q10keyboard.setBacklight(0); } + if (cardkb_found.address == MPR121_KB_ADDR) { + MPRkeyboard.begin(MPR121_KB_ADDR, &Wire1); + } break; #endif case ScanI2C::WIRE: @@ -49,6 +52,9 @@ int32_t KbI2cBase::runOnce() Q10keyboard.begin(BBQ10_KB_ADDR, &Wire); Q10keyboard.setBacklight(0); } + if (cardkb_found.address == MPR121_KB_ADDR) { + MPRkeyboard.begin(MPR121_KB_ADDR, &Wire); + } break; case ScanI2C::NO_I2C: default: @@ -157,6 +163,69 @@ int32_t KbI2cBase::runOnce() } break; } + case 0x37: { // MPR121 + MPRkeyboard.trigger(); + InputEvent e; + + while (MPRkeyboard.hasEvent()) { + char nextEvent = MPRkeyboard.dequeueEvent(); + e.inputEvent = ANYKEY; + e.kbchar = 0x00; + e.source = this->_originName; + switch (nextEvent) { + case 0x00: // MPR121_NONE + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE; + e.kbchar = 0x00; + break; + case 0x90: // MPR121_REBOOT + e.inputEvent = ANYKEY; + e.kbchar = INPUT_BROKER_MSG_REBOOT; + break; + case 0xb4: // MPR121_LEFT + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT; + e.kbchar = 0x00; + break; + case 0xb5: // MPR121_UP + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP; + e.kbchar = 0x00; + break; + case 0xb6: // MPR121_DOWN + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN; + e.kbchar = 0x00; + break; + case 0xb7: // MPR121_RIGHT + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT; + e.kbchar = 0x00; + break; + case 0x1b: // MPR121_ESC + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL; + e.kbchar = 0x1b; + break; + case 0x08: // MPR121_BSP + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK; + e.kbchar = 0x08; + break; + case 0x0d: // MPR121_SELECT + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT; + e.kbchar = 0x0d; + break; + default: + if (nextEvent > 127) { + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE; + e.kbchar = 0x00; + break; + } + e.inputEvent = ANYKEY; + e.kbchar = nextEvent; + break; + } + if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) { + LOG_DEBUG("MP121 Notifying: %i Char: %i", e.inputEvent, e.kbchar); + this->notifyObservers(&e); + } + } + break; + } case 0x02: { // RAK14004 uint8_t rDataBuf[8] = {0}; diff --git a/src/input/kbI2cBase.h b/src/input/kbI2cBase.h index 35b9b0901..dc2414fc0 100644 --- a/src/input/kbI2cBase.h +++ b/src/input/kbI2cBase.h @@ -2,6 +2,7 @@ #include "BBQ10Keyboard.h" #include "InputBroker.h" +#include "MPR121Keyboard.h" #include "Wire.h" #include "concurrency/OSThread.h" @@ -19,5 +20,6 @@ class KbI2cBase : public Observable, public concurrency::OST TwoWire *i2cBus = 0; BBQ10Keyboard Q10keyboard; + MPR121Keyboard MPRkeyboard; bool is_sym = false; -}; +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 6abdb18f7..3c1406a65 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -523,6 +523,10 @@ void setup() // assign an arbitrary value to distinguish from other models kb_model = 0x11; break; + case ScanI2C::DeviceType::MPR121KB: + // assign an arbitrary value to distinguish from other models + kb_model = 0x37; + break; default: // use this as default since it's also just zero LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00", kb_info.type); From a4705d2c190b8d6ae4a7059e08b894ff1fc6f4e8 Mon Sep 17 00:00:00 2001 From: Robert Date: Mon, 21 Oct 2024 03:25:27 -0500 Subject: [PATCH 17/20] add RFC 3927 IP address space to private IP checks (#5115) Add the RFC 3927 IP address block (169.254.0.0/16), also referred to as IPIPA, to the private address checks for MQTT functionality. --- src/mqtt/MQTT.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index 3ad397beb..2a2018395 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -746,7 +746,8 @@ bool MQTT::isPrivateIpAddress(const char address[]) } // Check the easy ones first. - if (strcmp(address, "127.0.0.1") == 0 || strncmp(address, "10.", 3) == 0 || strncmp(address, "192.168", 7) == 0) { + if (strcmp(address, "127.0.0.1") == 0 || strncmp(address, "10.", 3) == 0 || strncmp(address, "192.168", 7) == 0 || + strncmp(address, "169.254", 7) == 0) { return true; } From 4416ac57cf0d5a8042aca0e967772c45ca2c9222 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 16:06:56 -0500 Subject: [PATCH 18/20] [create-pull-request] automated change (#5124) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/config.pb.h | 9 ++++++--- src/mesh/generated/meshtastic/mesh.pb.h | 11 ++++++----- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/protobufs b/protobufs index 0fed5c770..8686d049c 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 0fed5c7709d2cec043a0f6daefa86ff11de0b946 +Subproject commit 8686d049c22c232f57121e66dfb29e7be65010f0 diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index 72a89fcdf..4c76e74cb 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -75,7 +75,10 @@ typedef enum _meshtastic_Config_DeviceConfig_RebroadcastMode { but takes it step further by also ignoring messages from nodenums not in the node's known list (NodeDB) */ meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY = 3, /* Only permitted for SENSOR, TRACKER and TAK_TRACKER roles, this will inhibit all rebroadcasts, not unlike CLIENT_MUTE role. */ - meshtastic_Config_DeviceConfig_RebroadcastMode_NONE = 4 + meshtastic_Config_DeviceConfig_RebroadcastMode_NONE = 4, + /* Ignores packets from non-standard portnums such as: TAK, RangeTest, PaxCounter, etc. + Only rebroadcasts packets with standard portnums: NodeInfo, Text, Position, Telemetry, and Routing. */ + meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY = 5 } meshtastic_Config_DeviceConfig_RebroadcastMode; /* Bit field of boolean configuration options, indicating which optional @@ -587,8 +590,8 @@ extern "C" { #define _meshtastic_Config_DeviceConfig_Role_ARRAYSIZE ((meshtastic_Config_DeviceConfig_Role)(meshtastic_Config_DeviceConfig_Role_TAK_TRACKER+1)) #define _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN meshtastic_Config_DeviceConfig_RebroadcastMode_ALL -#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MAX meshtastic_Config_DeviceConfig_RebroadcastMode_NONE -#define _meshtastic_Config_DeviceConfig_RebroadcastMode_ARRAYSIZE ((meshtastic_Config_DeviceConfig_RebroadcastMode)(meshtastic_Config_DeviceConfig_RebroadcastMode_NONE+1)) +#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MAX meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY +#define _meshtastic_Config_DeviceConfig_RebroadcastMode_ARRAYSIZE ((meshtastic_Config_DeviceConfig_RebroadcastMode)(meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY+1)) #define _meshtastic_Config_PositionConfig_PositionFlags_MIN meshtastic_Config_PositionConfig_PositionFlags_UNSET #define _meshtastic_Config_PositionConfig_PositionFlags_MAX meshtastic_Config_PositionConfig_PositionFlags_SPEED diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 97bf802c1..17254354c 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -765,6 +765,7 @@ typedef struct _meshtastic_NodeInfo { bool is_favorite; } meshtastic_NodeInfo; +typedef PB_BYTES_ARRAY_T(16) meshtastic_MyNodeInfo_device_id_t; /* Unique local debugging info for this node Note: we don't include position or the user info, because that will come in the Sent to the phone in response to WantNodes. */ @@ -779,7 +780,7 @@ typedef struct _meshtastic_MyNodeInfo { Phone/PC apps should compare this to their build number and if too low tell the user they must update their app */ uint32_t min_app_version; /* Unique hardware identifier for this device */ - uint64_t device_id; + meshtastic_MyNodeInfo_device_id_t device_id; } meshtastic_MyNodeInfo; /* Debug output from the device. @@ -1114,7 +1115,7 @@ extern "C" { #define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0} #define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0} -#define meshtastic_MyNodeInfo_init_default {0, 0, 0, 0} +#define meshtastic_MyNodeInfo_init_default {0, 0, 0, {0, {0}}} #define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN} #define meshtastic_QueueStatus_init_default {0, 0, 0, 0} #define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}} @@ -1139,7 +1140,7 @@ extern "C" { #define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0} #define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0} -#define meshtastic_MyNodeInfo_init_zero {0, 0, 0, 0} +#define meshtastic_MyNodeInfo_init_zero {0, 0, 0, {0, {0}}} #define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN} #define meshtastic_QueueStatus_init_zero {0, 0, 0, 0} #define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}} @@ -1450,7 +1451,7 @@ X(a, STATIC, SINGULAR, BOOL, is_favorite, 10) X(a, STATIC, SINGULAR, UINT32, my_node_num, 1) \ X(a, STATIC, SINGULAR, UINT32, reboot_count, 8) \ X(a, STATIC, SINGULAR, UINT32, min_app_version, 11) \ -X(a, STATIC, SINGULAR, UINT64, device_id, 12) +X(a, STATIC, SINGULAR, BYTES, device_id, 12) #define meshtastic_MyNodeInfo_CALLBACK NULL #define meshtastic_MyNodeInfo_DEFAULT NULL @@ -1673,7 +1674,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_LogRecord_size 426 #define meshtastic_MeshPacket_size 367 #define meshtastic_MqttClientProxyMessage_size 501 -#define meshtastic_MyNodeInfo_size 29 +#define meshtastic_MyNodeInfo_size 36 #define meshtastic_NeighborInfo_size 258 #define meshtastic_Neighbor_size 22 #define meshtastic_NodeInfo_size 317 From 3f1c86f9535279fd17eaaab6e10a06f09915b7e4 Mon Sep 17 00:00:00 2001 From: Craig Bailey Date: Tue, 22 Oct 2024 17:22:10 -0400 Subject: [PATCH 19/20] Update meshtasticd.service (#5118) Adding restart on service failure with 3 seconds between restart to stop fasst restart loops. Adding StartLimitBurst to limit it to 5 restarts in 200 seconds. --- bin/meshtasticd.service | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bin/meshtasticd.service b/bin/meshtasticd.service index f15fdc871..1e8ee98b8 100644 --- a/bin/meshtasticd.service +++ b/bin/meshtasticd.service @@ -1,12 +1,16 @@ [Unit] Description=Meshtastic Native Daemon After=network-online.target +StartLimitInterval=200 +StartLimitBurst=5 [Service] User=root Group=root Type=simple ExecStart=/usr/sbin/meshtasticd +Restart=always +RestartSec=3 [Install] -WantedBy=multi-user.target \ No newline at end of file +WantedBy=multi-user.target From 57667f10281b79c406b5278086986500e5e23602 Mon Sep 17 00:00:00 2001 From: panaceya Date: Wed, 23 Oct 2024 13:26:44 +0300 Subject: [PATCH 20/20] ADD: Configurable UPLINK_ENABLED and DOWNLINK_ENABLED in userPrefs.h (#5120) --- src/mesh/Channels.cpp | 21 ++++++++++++++++++--- userPrefs.h | 6 ++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp index 211d9afd4..b9fe95678 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -117,13 +117,18 @@ void Channels::initDefaultChannel(ChannelIndex chIndex) static const uint8_t defaultpsk0[] = USERPREFS_CHANNEL_0_PSK; memcpy(channelSettings.psk.bytes, defaultpsk0, sizeof(defaultpsk0)); channelSettings.psk.size = sizeof(defaultpsk0); - #endif #ifdef USERPREFS_CHANNEL_0_NAME strcpy(channelSettings.name, USERPREFS_CHANNEL_0_NAME); #endif #ifdef USERPREFS_CHANNEL_0_PRECISION channelSettings.module_settings.position_precision = USERPREFS_CHANNEL_0_PRECISION; +#endif +#ifdef USERPREFS_CHANNEL_0_UPLINK_ENABLED + channelSettings.uplink_enabled = USERPREFS_CHANNEL_0_UPLINK_ENABLED; +#endif +#ifdef USERPREFS_CHANNEL_0_DOWNLINK_ENABLED + channelSettings.downlink_enabled = USERPREFS_CHANNEL_0_DOWNLINK_ENABLED; #endif break; case 1: @@ -131,13 +136,18 @@ void Channels::initDefaultChannel(ChannelIndex chIndex) static const uint8_t defaultpsk1[] = USERPREFS_CHANNEL_1_PSK; memcpy(channelSettings.psk.bytes, defaultpsk1, sizeof(defaultpsk1)); channelSettings.psk.size = sizeof(defaultpsk1); - #endif #ifdef USERPREFS_CHANNEL_1_NAME strcpy(channelSettings.name, USERPREFS_CHANNEL_1_NAME); #endif #ifdef USERPREFS_CHANNEL_1_PRECISION channelSettings.module_settings.position_precision = USERPREFS_CHANNEL_1_PRECISION; +#endif +#ifdef USERPREFS_CHANNEL_1_UPLINK_ENABLED + channelSettings.uplink_enabled = USERPREFS_CHANNEL_1_UPLINK_ENABLED; +#endif +#ifdef USERPREFS_CHANNEL_1_DOWNLINK_ENABLED + channelSettings.downlink_enabled = USERPREFS_CHANNEL_1_DOWNLINK_ENABLED; #endif break; case 2: @@ -145,13 +155,18 @@ void Channels::initDefaultChannel(ChannelIndex chIndex) static const uint8_t defaultpsk2[] = USERPREFS_CHANNEL_2_PSK; memcpy(channelSettings.psk.bytes, defaultpsk2, sizeof(defaultpsk2)); channelSettings.psk.size = sizeof(defaultpsk2); - #endif #ifdef USERPREFS_CHANNEL_2_NAME strcpy(channelSettings.name, USERPREFS_CHANNEL_2_NAME); #endif #ifdef USERPREFS_CHANNEL_2_PRECISION channelSettings.module_settings.position_precision = USERPREFS_CHANNEL_2_PRECISION; +#endif +#ifdef USERPREFS_CHANNEL_2_UPLINK_ENABLED + channelSettings.uplink_enabled = USERPREFS_CHANNEL_2_UPLINK_ENABLED; +#endif +#ifdef USERPREFS_CHANNEL_2_DOWNLINK_ENABLED + channelSettings.downlink_enabled = USERPREFS_CHANNEL_2_DOWNLINK_ENABLED; #endif break; default: diff --git a/userPrefs.h b/userPrefs.h index ed622bcfb..58a44fef0 100644 --- a/userPrefs.h +++ b/userPrefs.h @@ -26,6 +26,8 @@ */ // #define USERPREFS_CHANNEL_0_NAME "DEFCONnect" // #define USERPREFS_CHANNEL_0_PRECISION 14 +// #define USERPREFS_CHANNEL_0_UPLINK_ENABLED true +// #define USERPREFS_CHANNEL_0_DOWNLINK_ENABLED true /* #define USERPREFS_CHANNEL_1_PSK \ { \ @@ -35,6 +37,8 @@ */ // #define USERPREFS_CHANNEL_1_NAME "REPLACEME" // #define USERPREFS_CHANNEL_1_PRECISION 14 +// #define USERPREFS_CHANNEL_1_UPLINK_ENABLED true +// #define USERPREFS_CHANNEL_1_DOWNLINK_ENABLED true /* #define USERPREFS_CHANNEL_2_PSK \ { \ @@ -44,6 +48,8 @@ */ // #define USERPREFS_CHANNEL_2_NAME "REPLACEME" // #define USERPREFS_CHANNEL_2_PRECISION 14 +// #define USERPREFS_CHANNEL_2_UPLINK_ENABLED true +// #define USERPREFS_CHANNEL_2_DOWNLINK_ENABLED true // #define USERPREFS_CONFIG_OWNER_LONG_NAME "My Long Name" // #define USERPREFS_CONFIG_OWNER_SHORT_NAME "MLN"