From f16402dec152df25c35c953186418321e8bb26bb Mon Sep 17 00:00:00 2001 From: Austin Date: Wed, 14 May 2025 14:39:46 -0400 Subject: [PATCH 01/21] MQTT userprefs (#6802) --- src/mesh/Channels.cpp | 2 +- src/mesh/Default.h | 2 ++ src/mesh/NodeDB.cpp | 30 +++++++++++++++++++++++++++++- src/mqtt/MQTT.cpp | 7 +++++++ src/mqtt/MQTT.h | 2 ++ userPrefs.jsonc | 7 +++++++ 6 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp index 2ba3499f1..70e4127d8 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -347,7 +347,7 @@ bool Channels::anyMqttEnabled() { #if USERPREFS_EVENT_MODE && !MESHTASTIC_EXCLUDE_MQTT // Don't publish messages on the public MQTT broker if we are in event mode - if (mqtt && mqtt->isUsingDefaultServer()) { + if (mqtt && mqtt->isUsingDefaultServer() && mqtt->isUsingDefaultRootTopic()) { return false; } #endif diff --git a/src/mesh/Default.h b/src/mesh/Default.h index 0daccbb6f..bc2aa785f 100644 --- a/src/mesh/Default.h +++ b/src/mesh/Default.h @@ -26,6 +26,8 @@ #define default_mqtt_username "meshdev" #define default_mqtt_password "large4cats" #define default_mqtt_root "msh" +#define default_mqtt_encryption_enabled true +#define default_mqtt_tls_enabled false #define IF_ROUTER(routerVal, normalVal) \ ((config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER) ? (routerVal) : (normalVal)) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 0495fa7aa..f22f7bf91 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -761,11 +761,39 @@ void NodeDB::installDefaultModuleConfig() moduleConfig.has_canned_message = true; +#if USERPREFS_MQTT_ENABLED && !MESHTASTIC_EXCLUDE_MQTT + moduleConfig.mqtt.enabled = true; +#endif +#ifdef USERPREFS_MQTT_ADDRESS + strncpy(moduleConfig.mqtt.address, USERPREFS_MQTT_ADDRESS, sizeof(moduleConfig.mqtt.address)); +#else strncpy(moduleConfig.mqtt.address, default_mqtt_address, sizeof(moduleConfig.mqtt.address)); +#endif +#ifdef USERPREFS_MQTT_USERNAME + strncpy(moduleConfig.mqtt.username, USERPREFS_MQTT_USERNAME, sizeof(moduleConfig.mqtt.username)); +#else strncpy(moduleConfig.mqtt.username, default_mqtt_username, sizeof(moduleConfig.mqtt.username)); +#endif +#ifdef USERPREFS_MQTT_PASSWORD + strncpy(moduleConfig.mqtt.password, USERPREFS_MQTT_PASSWORD, sizeof(moduleConfig.mqtt.password)); +#else strncpy(moduleConfig.mqtt.password, default_mqtt_password, sizeof(moduleConfig.mqtt.password)); +#endif +#ifdef USERPREFS_MQTT_ROOT_TOPIC + strncpy(moduleConfig.mqtt.root, USERPREFS_MQTT_ROOT_TOPIC, sizeof(moduleConfig.mqtt.root)); +#else strncpy(moduleConfig.mqtt.root, default_mqtt_root, sizeof(moduleConfig.mqtt.root)); - moduleConfig.mqtt.encryption_enabled = true; +#endif +#ifdef USERPREFS_MQTT_ENCRYPTION_ENABLED + moduleConfig.mqtt.encryption_enabled = USERPREFS_MQTT_ENCRYPTION_ENABLED; +#else + moduleConfig.mqtt.encryption_enabled = default_mqtt_encryption_enabled; +#endif +#ifdef USERPREFS_MQTT_TLS_ENABLED + moduleConfig.mqtt.tls_enabled = USERPREFS_MQTT_TLS_ENABLED; +#else + moduleConfig.mqtt.tls_enabled = default_mqtt_tls_enabled; +#endif moduleConfig.has_neighbor_info = true; moduleConfig.neighbor_info.enabled = false; diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index fb92789ee..3776f59f5 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -256,6 +256,11 @@ bool isDefaultServer(const String &host) return host.length() == 0 || host == default_mqtt_address; } +bool isDefaultRootTopic(const String &root) +{ + return root.length() == 0 || root == default_mqtt_root; +} + struct PubSubConfig { explicit PubSubConfig(const meshtastic_ModuleConfig_MQTTConfig &config) { @@ -387,10 +392,12 @@ MQTT::MQTT() : concurrency::OSThread("mqtt"), mqttQueue(MAX_MQTT_QUEUE) cryptTopic = moduleConfig.mqtt.root + cryptTopic; jsonTopic = moduleConfig.mqtt.root + jsonTopic; mapTopic = moduleConfig.mqtt.root + mapTopic; + isConfiguredForDefaultRootTopic = isDefaultRootTopic(moduleConfig.mqtt.root); } else { cryptTopic = "msh" + cryptTopic; jsonTopic = "msh" + jsonTopic; mapTopic = "msh" + mapTopic; + isConfiguredForDefaultRootTopic = true; } if (moduleConfig.mqtt.map_reporting_enabled && moduleConfig.mqtt.has_map_report_settings) { diff --git a/src/mqtt/MQTT.h b/src/mqtt/MQTT.h index 0c260dc9c..2b11f479d 100644 --- a/src/mqtt/MQTT.h +++ b/src/mqtt/MQTT.h @@ -58,6 +58,7 @@ class MQTT : private concurrency::OSThread void start() { setIntervalFromNow(0); }; bool isUsingDefaultServer() { return isConfiguredForDefaultServer; } + bool isUsingDefaultRootTopic() { return isConfiguredForDefaultRootTopic; } /// Validate the meshtastic_ModuleConfig_MQTTConfig. static bool isValidConfig(const meshtastic_ModuleConfig_MQTTConfig &config) { return isValidConfig(config, nullptr); } @@ -71,6 +72,7 @@ class MQTT : private concurrency::OSThread int reconnectCount = 0; bool isConfiguredForDefaultServer = true; + bool isConfiguredForDefaultRootTopic = true; virtual int32_t runOnce() override; diff --git a/userPrefs.jsonc b/userPrefs.jsonc index 06c4a7eec..a349a5700 100644 --- a/userPrefs.jsonc +++ b/userPrefs.jsonc @@ -44,5 +44,12 @@ // "USERPREFS_NETWORK_WIFI_ENABLED": "true", // "USERPREFS_NETWORK_WIFI_SSID": "wifi_ssid", // "USERPREFS_NETWORK_WIFI_PSK": "wifi_psk", + // "USERPREFS_MQTT_ENABLED": "1", + // "USERPREFS_MQTT_ADDRESS": "'mqtt.meshtastic.org'", + // "USERPREFS_MQTT_USERNAME": "meshdev", + // "USERPREFS_MQTT_PASSWORD": "large4cats", + // "USERPREFS_MQTT_ENCRYPTION_ENABLED": "true", + // "USERPREFS_MQTT_TLS_ENABLED": "false", + // "USERPREFS_MQTT_ROOT_TOPIC": "event/REPLACEME", "USERPREFS_TZ_STRING": "tzplaceholder " } From bc313da064abee20474a8e078d865ffd18658916 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 13:48:14 -0500 Subject: [PATCH 02/21] [create-pull-request] automated change (#6810) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/admin.pb.h | 2 +- src/mesh/generated/meshtastic/deviceonly.pb.h | 19 ++++++++++++------- src/mesh/generated/meshtastic/mesh.pb.h | 15 ++++++++++----- src/mesh/generated/meshtastic/telemetry.pb.h | 8 +++++--- 5 files changed, 29 insertions(+), 17 deletions(-) diff --git a/protobufs b/protobufs index 816595c8b..8cb3e62a0 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 816595c8bbdfc3b4388e11348ccd043294d58705 +Subproject commit 8cb3e62a0d35d470e3d5d9950c0f1d85ccb35b22 diff --git a/src/mesh/generated/meshtastic/admin.pb.h b/src/mesh/generated/meshtastic/admin.pb.h index 09499b075..0a46e6275 100644 --- a/src/mesh/generated/meshtastic/admin.pb.h +++ b/src/mesh/generated/meshtastic/admin.pb.h @@ -446,7 +446,7 @@ extern const pb_msgdesc_t meshtastic_SharedContact_msg; #define meshtastic_AdminMessage_size 511 #define meshtastic_HamParameters_size 31 #define meshtastic_NodeRemoteHardwarePinsResponse_size 496 -#define meshtastic_SharedContact_size 121 +#define meshtastic_SharedContact_size 123 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index 83563a9fc..5e92cacd0 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -58,6 +58,9 @@ typedef struct _meshtastic_UserLite { /* The public key of the user's device. This is sent out to other nodes on the mesh to allow them to compute a shared secret key. */ meshtastic_UserLite_public_key_t public_key; + /* Whether or not the node can be messaged */ + bool has_is_unmessagable; + bool is_unmessagable; } meshtastic_UserLite; typedef struct _meshtastic_NodeInfoLite { @@ -183,14 +186,14 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_PositionLite_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN} -#define meshtastic_UserLite_init_default {{0}, "", "", _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}} +#define meshtastic_UserLite_init_default {{0}, "", "", _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}, false, 0} #define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_UserLite_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0, 0} #define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default, 0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}} #define meshtastic_NodeDatabase_init_default {0, {0}} #define meshtastic_ChannelFile_init_default {0, {meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default}, 0} #define meshtastic_BackupPreferences_init_default {0, 0, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default, false, meshtastic_ChannelFile_init_default, false, meshtastic_User_init_default} #define meshtastic_PositionLite_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN} -#define meshtastic_UserLite_init_zero {{0}, "", "", _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}} +#define meshtastic_UserLite_init_zero {{0}, "", "", _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}, false, 0} #define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_UserLite_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0, 0} #define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero, 0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}} #define meshtastic_NodeDatabase_init_zero {0, {0}} @@ -210,6 +213,7 @@ extern "C" { #define meshtastic_UserLite_is_licensed_tag 5 #define meshtastic_UserLite_role_tag 6 #define meshtastic_UserLite_public_key_tag 7 +#define meshtastic_UserLite_is_unmessagable_tag 9 #define meshtastic_NodeInfoLite_num_tag 1 #define meshtastic_NodeInfoLite_user_tag 2 #define meshtastic_NodeInfoLite_position_tag 3 @@ -259,7 +263,8 @@ X(a, STATIC, SINGULAR, STRING, short_name, 3) \ X(a, STATIC, SINGULAR, UENUM, hw_model, 4) \ X(a, STATIC, SINGULAR, BOOL, is_licensed, 5) \ X(a, STATIC, SINGULAR, UENUM, role, 6) \ -X(a, STATIC, SINGULAR, BYTES, public_key, 7) +X(a, STATIC, SINGULAR, BYTES, public_key, 7) \ +X(a, STATIC, OPTIONAL, BOOL, is_unmessagable, 9) #define meshtastic_UserLite_CALLBACK NULL #define meshtastic_UserLite_DEFAULT NULL @@ -350,12 +355,12 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg; /* Maximum encoded size of messages (where known) */ /* meshtastic_NodeDatabase_size depends on runtime parameters */ #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size -#define meshtastic_BackupPreferences_size 2263 +#define meshtastic_BackupPreferences_size 2265 #define meshtastic_ChannelFile_size 718 -#define meshtastic_DeviceState_size 1720 -#define meshtastic_NodeInfoLite_size 188 +#define meshtastic_DeviceState_size 1722 +#define meshtastic_NodeInfoLite_size 190 #define meshtastic_PositionLite_size 28 -#define meshtastic_UserLite_size 96 +#define meshtastic_UserLite_size 98 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 6fa0b60b0..572a6f5d5 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -609,6 +609,9 @@ typedef struct _meshtastic_User { /* The public key of the user's device. This is sent out to other nodes on the mesh to allow them to compute a shared secret key. */ meshtastic_User_public_key_t public_key; + /* Whether or not the node can be messaged */ + bool has_is_unmessagable; + bool is_unmessagable; } meshtastic_User; /* A message used in a traceroute */ @@ -1204,7 +1207,7 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_Position_init_default {false, 0, false, 0, false, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, false, 0, false, 0, 0, 0, 0, 0, false, 0, false, 0, 0, 0, 0, 0, 0, 0, 0} -#define meshtastic_User_init_default {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}} +#define meshtastic_User_init_default {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}, false, 0} #define meshtastic_RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}} #define meshtastic_Routing_init_default {0, {meshtastic_RouteDiscovery_init_default}} #define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0} @@ -1229,7 +1232,7 @@ extern "C" { #define meshtastic_resend_chunks_init_default {{{NULL}, NULL}} #define meshtastic_ChunkedPayloadResponse_init_default {0, 0, {0}} #define meshtastic_Position_init_zero {false, 0, false, 0, false, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, false, 0, false, 0, 0, 0, 0, 0, false, 0, false, 0, 0, 0, 0, 0, 0, 0, 0} -#define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}} +#define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN, {0, {0}}, false, 0} #define meshtastic_RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}} #define meshtastic_Routing_init_zero {0, {meshtastic_RouteDiscovery_init_zero}} #define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0} @@ -1286,6 +1289,7 @@ extern "C" { #define meshtastic_User_is_licensed_tag 6 #define meshtastic_User_role_tag 7 #define meshtastic_User_public_key_tag 8 +#define meshtastic_User_is_unmessagable_tag 9 #define meshtastic_RouteDiscovery_route_tag 1 #define meshtastic_RouteDiscovery_snr_towards_tag 2 #define meshtastic_RouteDiscovery_route_back_tag 3 @@ -1457,7 +1461,8 @@ X(a, STATIC, SINGULAR, FIXED_LENGTH_BYTES, macaddr, 4) \ X(a, STATIC, SINGULAR, UENUM, hw_model, 5) \ X(a, STATIC, SINGULAR, BOOL, is_licensed, 6) \ X(a, STATIC, SINGULAR, UENUM, role, 7) \ -X(a, STATIC, SINGULAR, BYTES, public_key, 8) +X(a, STATIC, SINGULAR, BYTES, public_key, 8) \ +X(a, STATIC, OPTIONAL, BOOL, is_unmessagable, 9) #define meshtastic_User_CALLBACK NULL #define meshtastic_User_DEFAULT NULL @@ -1786,14 +1791,14 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_MyNodeInfo_size 77 #define meshtastic_NeighborInfo_size 258 #define meshtastic_Neighbor_size 22 -#define meshtastic_NodeInfo_size 319 +#define meshtastic_NodeInfo_size 321 #define meshtastic_NodeRemoteHardwarePin_size 29 #define meshtastic_Position_size 144 #define meshtastic_QueueStatus_size 23 #define meshtastic_RouteDiscovery_size 256 #define meshtastic_Routing_size 259 #define meshtastic_ToRadio_size 504 -#define meshtastic_User_size 113 +#define meshtastic_User_size 115 #define meshtastic_Waypoint_size 165 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index dcc511ea6..be3fa0907 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -87,7 +87,9 @@ typedef enum _meshtastic_TelemetrySensorType { /* Infineon DPS310 High accuracy pressure and temperature */ meshtastic_TelemetrySensorType_DPS310 = 36, /* RAKWireless RAK12035 Soil Moisture Sensor Module */ - meshtastic_TelemetrySensorType_RAK12035 = 37 + meshtastic_TelemetrySensorType_RAK12035 = 37, + /* MAX17261 lipo battery gauge */ + meshtastic_TelemetrySensorType_MAX17261 = 38 } meshtastic_TelemetrySensorType; /* Struct definitions */ @@ -324,8 +326,8 @@ extern "C" { /* Helper constants for enums */ #define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET -#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_RAK12035 -#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_RAK12035+1)) +#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_MAX17261 +#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_MAX17261+1)) From 1af4a0bdc9ab66081a6ccb5e1444e1d15b807083 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 14:10:45 -0500 Subject: [PATCH 03/21] Upgrade trunk (#6797) Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com> --- .trunk/trunk.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index ca38c978a..4aa5527be 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -10,13 +10,13 @@ lint: enabled: - renovate@40.0.6 - prettier@3.5.3 - - trufflehog@3.88.28 + - trufflehog@3.88.29 - yamllint@1.37.1 - bandit@1.8.3 - terrascan@1.19.9 - trivy@0.62.1 - taplo@0.9.3 - - ruff@0.11.8 + - ruff@0.11.9 - isort@6.0.1 - markdownlint@0.44.0 - oxipng@9.1.5 @@ -28,7 +28,7 @@ lint: - shellcheck@0.10.0 - black@25.1.0 - git-diff-check - - gitleaks@8.25.1 + - gitleaks@8.26.0 - clang-format@16.0.3 ignore: - linters: [ALL] From a51a6b8c475cdd654dc3c12ccff33340be6709cd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 14:41:37 -0500 Subject: [PATCH 04/21] [create-pull-request] automated change (#6812) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/deviceonly.pb.h | 2 +- src/mesh/generated/meshtastic/localonly.pb.h | 2 +- src/mesh/generated/meshtastic/module_config.pb.h | 16 ++++++++++------ src/mesh/generated/meshtastic/mqtt.pb.h | 13 +++++++++---- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/protobufs b/protobufs index 8cb3e62a0..47ec99aa4 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 8cb3e62a0d35d470e3d5d9950c0f1d85ccb35b22 +Subproject commit 47ec99aa4c4a2e3fff71fd5170663f0848deb021 diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index 5e92cacd0..d29fb17a7 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -355,7 +355,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg; /* Maximum encoded size of messages (where known) */ /* meshtastic_NodeDatabase_size depends on runtime parameters */ #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size -#define meshtastic_BackupPreferences_size 2265 +#define meshtastic_BackupPreferences_size 2267 #define meshtastic_ChannelFile_size 718 #define meshtastic_DeviceState_size 1722 #define meshtastic_NodeInfoLite_size 190 diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index 6a59b8eb0..53d8d7d80 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -188,7 +188,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalConfig_size #define meshtastic_LocalConfig_size 743 -#define meshtastic_LocalModuleConfig_size 667 +#define meshtastic_LocalModuleConfig_size 669 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h index dbf6ddb2e..e8ae48072 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.h +++ b/src/mesh/generated/meshtastic/module_config.pb.h @@ -112,6 +112,8 @@ typedef struct _meshtastic_ModuleConfig_MapReportSettings { uint32_t publish_interval_secs; /* Bits of precision for the location sent (default of 32 is full precision). */ uint32_t position_precision; + /* Whether we have opted-in to report our location to the map */ + bool should_report_location; } meshtastic_ModuleConfig_MapReportSettings; /* MQTT Client Config */ @@ -505,7 +507,7 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_ModuleConfig_init_default {0, {meshtastic_ModuleConfig_MQTTConfig_init_default}} #define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0, "", 0, 0, false, meshtastic_ModuleConfig_MapReportSettings_init_default} -#define meshtastic_ModuleConfig_MapReportSettings_init_default {0, 0} +#define meshtastic_ModuleConfig_MapReportSettings_init_default {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, 0} #define meshtastic_ModuleConfig_DetectionSensorConfig_init_default {0, 0, 0, 0, "", 0, _meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_MIN, 0} @@ -521,7 +523,7 @@ extern "C" { #define meshtastic_RemoteHardwarePin_init_default {0, "", _meshtastic_RemoteHardwarePinType_MIN} #define meshtastic_ModuleConfig_init_zero {0, {meshtastic_ModuleConfig_MQTTConfig_init_zero}} #define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0, "", 0, 0, false, meshtastic_ModuleConfig_MapReportSettings_init_zero} -#define meshtastic_ModuleConfig_MapReportSettings_init_zero {0, 0} +#define meshtastic_ModuleConfig_MapReportSettings_init_zero {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, 0} #define meshtastic_ModuleConfig_DetectionSensorConfig_init_zero {0, 0, 0, 0, "", 0, _meshtastic_ModuleConfig_DetectionSensorConfig_TriggerType_MIN, 0} @@ -539,6 +541,7 @@ extern "C" { /* Field tags (for use in manual encoding/decoding) */ #define meshtastic_ModuleConfig_MapReportSettings_publish_interval_secs_tag 1 #define meshtastic_ModuleConfig_MapReportSettings_position_precision_tag 2 +#define meshtastic_ModuleConfig_MapReportSettings_should_report_location_tag 3 #define meshtastic_ModuleConfig_MQTTConfig_enabled_tag 1 #define meshtastic_ModuleConfig_MQTTConfig_address_tag 2 #define meshtastic_ModuleConfig_MQTTConfig_username_tag 3 @@ -702,7 +705,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, map_report_settings, 11) #define meshtastic_ModuleConfig_MapReportSettings_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, publish_interval_secs, 1) \ -X(a, STATIC, SINGULAR, UINT32, position_precision, 2) +X(a, STATIC, SINGULAR, UINT32, position_precision, 2) \ +X(a, STATIC, SINGULAR, BOOL, should_report_location, 3) #define meshtastic_ModuleConfig_MapReportSettings_CALLBACK NULL #define meshtastic_ModuleConfig_MapReportSettings_DEFAULT NULL @@ -890,8 +894,8 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg; #define meshtastic_ModuleConfig_CannedMessageConfig_size 49 #define meshtastic_ModuleConfig_DetectionSensorConfig_size 44 #define meshtastic_ModuleConfig_ExternalNotificationConfig_size 42 -#define meshtastic_ModuleConfig_MQTTConfig_size 222 -#define meshtastic_ModuleConfig_MapReportSettings_size 12 +#define meshtastic_ModuleConfig_MQTTConfig_size 224 +#define meshtastic_ModuleConfig_MapReportSettings_size 14 #define meshtastic_ModuleConfig_NeighborInfoConfig_size 10 #define meshtastic_ModuleConfig_PaxcounterConfig_size 30 #define meshtastic_ModuleConfig_RangeTestConfig_size 10 @@ -899,7 +903,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg; #define meshtastic_ModuleConfig_SerialConfig_size 28 #define meshtastic_ModuleConfig_StoreForwardConfig_size 24 #define meshtastic_ModuleConfig_TelemetryConfig_size 46 -#define meshtastic_ModuleConfig_size 225 +#define meshtastic_ModuleConfig_size 227 #define meshtastic_RemoteHardwarePin_size 21 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/mqtt.pb.h b/src/mesh/generated/meshtastic/mqtt.pb.h index 1726bc470..c5b10f1f5 100644 --- a/src/mesh/generated/meshtastic/mqtt.pb.h +++ b/src/mesh/generated/meshtastic/mqtt.pb.h @@ -54,6 +54,9 @@ typedef struct _meshtastic_MapReport { uint32_t position_precision; /* Number of online nodes (heard in the last 2 hours) this node has in its list that were received locally (not via MQTT) */ uint16_t num_online_local_nodes; + /* User has opted in to share their location (map report) with the mqtt server + Controlled by map_report.should_report_location */ + bool has_opted_report_location; } meshtastic_MapReport; @@ -63,9 +66,9 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_ServiceEnvelope_init_default {NULL, NULL, NULL} -#define meshtastic_MapReport_init_default {"", "", _meshtastic_Config_DeviceConfig_Role_MIN, _meshtastic_HardwareModel_MIN, "", _meshtastic_Config_LoRaConfig_RegionCode_MIN, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, 0, 0} +#define meshtastic_MapReport_init_default {"", "", _meshtastic_Config_DeviceConfig_Role_MIN, _meshtastic_HardwareModel_MIN, "", _meshtastic_Config_LoRaConfig_RegionCode_MIN, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ServiceEnvelope_init_zero {NULL, NULL, NULL} -#define meshtastic_MapReport_init_zero {"", "", _meshtastic_Config_DeviceConfig_Role_MIN, _meshtastic_HardwareModel_MIN, "", _meshtastic_Config_LoRaConfig_RegionCode_MIN, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, 0, 0} +#define meshtastic_MapReport_init_zero {"", "", _meshtastic_Config_DeviceConfig_Role_MIN, _meshtastic_HardwareModel_MIN, "", _meshtastic_Config_LoRaConfig_RegionCode_MIN, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, 0, 0, 0} /* Field tags (for use in manual encoding/decoding) */ #define meshtastic_ServiceEnvelope_packet_tag 1 @@ -84,6 +87,7 @@ extern "C" { #define meshtastic_MapReport_altitude_tag 11 #define meshtastic_MapReport_position_precision_tag 12 #define meshtastic_MapReport_num_online_local_nodes_tag 13 +#define meshtastic_MapReport_has_opted_report_location_tag 14 /* Struct field encoding specification for nanopb */ #define meshtastic_ServiceEnvelope_FIELDLIST(X, a) \ @@ -107,7 +111,8 @@ X(a, STATIC, SINGULAR, SFIXED32, latitude_i, 9) \ X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 10) \ X(a, STATIC, SINGULAR, INT32, altitude, 11) \ X(a, STATIC, SINGULAR, UINT32, position_precision, 12) \ -X(a, STATIC, SINGULAR, UINT32, num_online_local_nodes, 13) +X(a, STATIC, SINGULAR, UINT32, num_online_local_nodes, 13) \ +X(a, STATIC, SINGULAR, BOOL, has_opted_report_location, 14) #define meshtastic_MapReport_CALLBACK NULL #define meshtastic_MapReport_DEFAULT NULL @@ -121,7 +126,7 @@ extern const pb_msgdesc_t meshtastic_MapReport_msg; /* Maximum encoded size of messages (where known) */ /* meshtastic_ServiceEnvelope_size depends on runtime parameters */ #define MESHTASTIC_MESHTASTIC_MQTT_PB_H_MAX_SIZE meshtastic_MapReport_size -#define meshtastic_MapReport_size 108 +#define meshtastic_MapReport_size 110 #ifdef __cplusplus } /* extern "C" */ From fc64bea6982a1d6f31b39e4def84e28e26e93988 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 14 May 2025 15:28:09 -0500 Subject: [PATCH 05/21] Unmessagable implementation and defaults (#6811) * Unmessagable implementation and defaults * Router and router late are unmessagable by default * Update src/modules/AdminModule.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/mesh/NodeDB.cpp | 16 ++++++++++++++++ src/modules/AdminModule.cpp | 10 +++++++++- src/modules/NodeInfoModule.cpp | 5 +++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index f22f7bf91..48d22c65d 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -819,10 +819,19 @@ void NodeDB::installRoleDefaults(meshtastic_Config_DeviceConfig_Role role) initConfigIntervals(); initModuleConfigIntervals(); config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY; + owner.has_is_unmessagable = true; + owner.is_unmessagable = true; + } else if (role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE) { + owner.has_is_unmessagable = true; + owner.is_unmessagable = true; } else if (role == meshtastic_Config_DeviceConfig_Role_REPEATER) { + owner.has_is_unmessagable = true; + owner.is_unmessagable = true; config.display.screen_on_secs = 1; config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY; } else if (role == meshtastic_Config_DeviceConfig_Role_SENSOR) { + owner.has_is_unmessagable = true; + owner.is_unmessagable = true; moduleConfig.telemetry.environment_measurement_enabled = true; moduleConfig.telemetry.environment_update_interval = 300; } else if (role == meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND) { @@ -837,7 +846,12 @@ void NodeDB::installRoleDefaults(meshtastic_Config_DeviceConfig_Role role) (meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE | meshtastic_Config_PositionConfig_PositionFlags_SPEED | meshtastic_Config_PositionConfig_PositionFlags_HEADING | meshtastic_Config_PositionConfig_PositionFlags_DOP); moduleConfig.telemetry.device_update_interval = ONE_DAY; + } else if (role == meshtastic_Config_DeviceConfig_Role_TRACKER) { + owner.has_is_unmessagable = true; + owner.is_unmessagable = true; } else if (role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) { + owner.has_is_unmessagable = true; + owner.is_unmessagable = true; config.device.node_info_broadcast_secs = ONE_DAY; config.position.position_broadcast_smart_enabled = true; config.position.position_broadcast_secs = 3 * 60; // Every 3 minutes @@ -970,6 +984,8 @@ void NodeDB::installDefaultDeviceState() #endif snprintf(owner.id, sizeof(owner.id), "!%08x", getNodeNum()); // Default node ID now based on nodenum memcpy(owner.macaddr, ourMacAddr, sizeof(owner.macaddr)); + owner.has_is_unmessagable = true; + owner.is_unmessagable = false; } // We reserve a few nodenums for future use diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index cbf82ae73..0fac15b15 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -504,6 +504,12 @@ void AdminModule::handleSetOwner(const meshtastic_User &o) sendWarning(licensedModeMessage); } } + if (owner.has_is_unmessagable != o.has_is_unmessagable || + (o.has_is_unmessagable && owner.is_unmessagable != o.is_unmessagable)) { + changed = 1; + owner.has_is_unmessagable = o.has_is_unmessagable || o.has_is_unmessagable; + owner.is_unmessagable = o.is_unmessagable; + } if (changed) { // If nothing really changed, don't broadcast on the network or write to flash service->reloadOwner(!hasOpenEditTransaction); @@ -553,8 +559,10 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) sendWarning(warning); } // If we're setting router role for the first time, install its intervals - if (existingRole != c.payload_variant.device.role) + if (existingRole != c.payload_variant.device.role) { nodeDB->installRoleDefaults(c.payload_variant.device.role); + changes |= SEGMENT_NODEDATABASE | SEGMENT_DEVICESTATE; // Some role defaults affect owner + } if (config.device.node_info_broadcast_secs < min_node_info_broadcast_secs) { LOG_DEBUG("Tried to set node_info_broadcast_secs too low, setting to %d", min_node_info_broadcast_secs); config.device.node_info_broadcast_secs = min_node_info_broadcast_secs; diff --git a/src/modules/NodeInfoModule.cpp b/src/modules/NodeInfoModule.cpp index ce4a6bd06..5142f2db0 100644 --- a/src/modules/NodeInfoModule.cpp +++ b/src/modules/NodeInfoModule.cpp @@ -86,6 +86,11 @@ meshtastic_MeshPacket *NodeInfoModule::allocReply() u.public_key.bytes[0] = 0; u.public_key.size = 0; } + // Coerce unmessagable for Repeater role + if (u.role == meshtastic_Config_DeviceConfig_Role_REPEATER) { + u.has_is_unmessagable = true; + u.is_unmessagable = true; + } LOG_INFO("Send owner %s/%s/%s", u.id, u.long_name, u.short_name); lastSentToMesh = millis(); From 7cffd9ba7083468816a63d3485c70e1a698dcda3 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 14 May 2025 15:31:28 -0500 Subject: [PATCH 06/21] Added new map report opt-in for compliance and limit map report (and default) to one hour (#6813) * Added new map report opt-in for compliance and limit map report (and default) to one hour * Trunk --- src/mesh/Default.h | 1 + src/mesh/NodeDB.cpp | 5 +++++ src/modules/AdminModule.cpp | 2 +- src/mqtt/MQTT.cpp | 4 +++- src/mqtt/MQTT.h | 4 ++-- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/mesh/Default.h b/src/mesh/Default.h index bc2aa785f..208f992c8 100644 --- a/src/mesh/Default.h +++ b/src/mesh/Default.h @@ -21,6 +21,7 @@ #define default_neighbor_info_broadcast_secs 6 * 60 * 60 #define min_node_info_broadcast_secs 60 * 60 // No regular broadcasts of more than once an hour #define min_neighbor_info_broadcast_secs 4 * 60 * 60 +#define default_map_publish_interval_secs 60 * 60 #define default_mqtt_address "mqtt.meshtastic.org" #define default_mqtt_username "meshdev" diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 48d22c65d..4b1a6d64d 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -328,6 +328,11 @@ NodeDB::NodeDB() moduleConfig.telemetry.health_update_interval = Default::getConfiguredOrMinimumValue( moduleConfig.telemetry.health_update_interval, min_default_telemetry_interval_secs); } + if (moduleConfig.mqtt.has_map_report_settings && + moduleConfig.mqtt.map_report_settings.publish_interval_secs < default_map_publish_interval_secs) { + moduleConfig.mqtt.map_report_settings.publish_interval_secs = default_map_publish_interval_secs; + } + // Ensure that the neighbor info update interval is coerced to the minimum moduleConfig.neighbor_info.update_interval = Default::getConfiguredOrMinimumValue(moduleConfig.neighbor_info.update_interval, min_neighbor_info_broadcast_secs); diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 0fac15b15..3ff4fa74d 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -504,7 +504,7 @@ void AdminModule::handleSetOwner(const meshtastic_User &o) sendWarning(licensedModeMessage); } } - if (owner.has_is_unmessagable != o.has_is_unmessagable || + if (owner.has_is_unmessagable != o.has_is_unmessagable || (o.has_is_unmessagable && owner.is_unmessagable != o.is_unmessagable)) { changed = 1; owner.has_is_unmessagable = o.has_is_unmessagable || o.has_is_unmessagable; diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index 3776f59f5..713077272 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -769,7 +769,8 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp_encrypted, const meshtastic_Me void MQTT::perhapsReportToMap() { - if (!moduleConfig.mqtt.map_reporting_enabled || !(moduleConfig.mqtt.proxy_to_client_enabled || isConnectedDirectly())) + if (!moduleConfig.mqtt.map_reporting_enabled || !moduleConfig.mqtt.map_report_settings.should_report_location || + !(moduleConfig.mqtt.proxy_to_client_enabled || isConnectedDirectly())) return; if (Throttle::isWithinTimespanMs(last_report_to_map, map_publish_interval_msecs)) @@ -801,6 +802,7 @@ void MQTT::perhapsReportToMap() mapReport.region = config.lora.region; mapReport.modem_preset = config.lora.modem_preset; mapReport.has_default_channel = channels.hasDefaultChannel(); + mapReport.has_opted_report_location = true; // Set position with precision (same as in PositionModule) if (map_position_precision < 32 && map_position_precision > 0) { diff --git a/src/mqtt/MQTT.h b/src/mqtt/MQTT.h index 2b11f479d..7d5715602 100644 --- a/src/mqtt/MQTT.h +++ b/src/mqtt/MQTT.h @@ -1,5 +1,6 @@ #pragma once +#include "Default.h" #include "configuration.h" #include "concurrency/OSThread.h" @@ -105,8 +106,7 @@ class MQTT : private concurrency::OSThread std::string mapTopic = "/2/map/"; // For protobuf-encoded MapReport messages // For map reporting (only applies when enabled) - const uint32_t default_map_position_precision = 14; // defaults to max. offset of ~1459m - const uint32_t default_map_publish_interval_secs = 60 * 15; // defaults to 15 minutes + const uint32_t default_map_position_precision = 14; // defaults to max. offset of ~1459m uint32_t last_report_to_map = 0; uint32_t map_position_precision = default_map_position_precision; uint32_t map_publish_interval_msecs = default_map_publish_interval_secs * 1000; From 3901ae8956d34130d436182224896aa0d27e890e Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 14 May 2025 16:44:32 -0500 Subject: [PATCH 07/21] Default --- test/test_mqtt/MQTT.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_mqtt/MQTT.cpp b/test/test_mqtt/MQTT.cpp index 50a98001a..feb9c7e83 100644 --- a/test/test_mqtt/MQTT.cpp +++ b/test/test_mqtt/MQTT.cpp @@ -308,8 +308,8 @@ const meshtastic_MeshPacket encrypted = { // Initialize mocks and configuration before running each test. void setUp(void) { - moduleConfig.mqtt = - meshtastic_ModuleConfig_MQTTConfig{.enabled = true, .map_reporting_enabled = true, .has_map_report_settings = true}; + moduleConfig.mqtt = meshtastic_ModuleConfig_MQTTConfig{ + .enabled = true, .map_reporting_enabled = true, .has_map_report_settings = true, .should_report_location = true}; channelFile.channels[0] = meshtastic_Channel{ .index = 0, .has_settings = true, From b63b73ab84562887338700c47c46eb6eec45827a Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 14 May 2025 17:16:46 -0500 Subject: [PATCH 08/21] Fix --- test/test_mqtt/MQTT.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/test_mqtt/MQTT.cpp b/test/test_mqtt/MQTT.cpp index feb9c7e83..a297dc229 100644 --- a/test/test_mqtt/MQTT.cpp +++ b/test/test_mqtt/MQTT.cpp @@ -308,8 +308,10 @@ const meshtastic_MeshPacket encrypted = { // Initialize mocks and configuration before running each test. void setUp(void) { - moduleConfig.mqtt = meshtastic_ModuleConfig_MQTTConfig{ - .enabled = true, .map_reporting_enabled = true, .has_map_report_settings = true, .should_report_location = true}; + moduleConfig.mqtt = + meshtastic_ModuleConfig_MQTTConfig{.enabled = true, .map_reporting_enabled = true, .has_map_report_settings = true}; + mqtt.map_report_settings = meshtastic_ModuleConfig_MQTTConfig_MapReportSettings{ + .position_precision = 14, .publish_interval_secs = 0, .should_report_location = true}; channelFile.channels[0] = meshtastic_Channel{ .index = 0, .has_settings = true, From ed6de5095e9cf3f89c9ce25dafeeab837173d6fd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 17:54:21 -0500 Subject: [PATCH 09/21] [create-pull-request] automated change (#6815) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- .../generated/meshtastic/telemetry.pb.cpp | 3 + src/mesh/generated/meshtastic/telemetry.pb.h | 55 ++++++++++++++++++- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/protobufs b/protobufs index 47ec99aa4..4eb0aebae 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 47ec99aa4c4a2e3fff71fd5170663f0848deb021 +Subproject commit 4eb0aebaef1304a5516b6fa864cb4c55daed9147 diff --git a/src/mesh/generated/meshtastic/telemetry.pb.cpp b/src/mesh/generated/meshtastic/telemetry.pb.cpp index c79941fa5..b54cbb00e 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.cpp +++ b/src/mesh/generated/meshtastic/telemetry.pb.cpp @@ -24,6 +24,9 @@ PB_BIND(meshtastic_LocalStats, meshtastic_LocalStats, AUTO) PB_BIND(meshtastic_HealthMetrics, meshtastic_HealthMetrics, AUTO) +PB_BIND(meshtastic_HostMetrics, meshtastic_HostMetrics, AUTO) + + PB_BIND(meshtastic_Telemetry, meshtastic_Telemetry, AUTO) diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index be3fa0907..1c5eb4843 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -290,6 +290,28 @@ typedef struct _meshtastic_HealthMetrics { float temperature; } meshtastic_HealthMetrics; +/* Linux host metrics */ +typedef struct _meshtastic_HostMetrics { + /* Host system uptime */ + uint32_t uptime_seconds; + /* Host system free memory */ + uint64_t freemem_bytes; + /* Host system disk space free for / */ + uint64_t diskfree1_bytes; + /* Secondary system disk space free */ + bool has_diskfree2_bytes; + uint64_t diskfree2_bytes; + /* Tertiary disk space free */ + bool has_diskfree3_bytes; + uint64_t diskfree3_bytes; + /* Host system one minute load in 1/100ths */ + uint16_t load1; + /* Host system five minute load in 1/100ths */ + uint16_t load5; + /* Host system fifteen minute load in 1/100ths */ + uint16_t load15; +} meshtastic_HostMetrics; + /* Types of Measurements the telemetry module is equipped to handle */ typedef struct _meshtastic_Telemetry { /* Seconds since 1970 - or 0 for unknown/unset */ @@ -308,6 +330,8 @@ typedef struct _meshtastic_Telemetry { meshtastic_LocalStats local_stats; /* Health telemetry metrics */ meshtastic_HealthMetrics health_metrics; + /* Linux host metrics */ + meshtastic_HostMetrics host_metrics; } variant; } meshtastic_Telemetry; @@ -338,6 +362,7 @@ extern "C" { + /* Initializer values for message structs */ #define meshtastic_DeviceMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_EnvironmentMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} @@ -345,6 +370,7 @@ extern "C" { #define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_HealthMetrics_init_default {false, 0, false, 0, false, 0} +#define meshtastic_HostMetrics_init_default {0, 0, 0, false, 0, false, 0, 0, 0, 0} #define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}} #define meshtastic_Nau7802Config_init_default {0, 0} #define meshtastic_DeviceMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0} @@ -353,6 +379,7 @@ extern "C" { #define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_HealthMetrics_init_zero {false, 0, false, 0, false, 0} +#define meshtastic_HostMetrics_init_zero {0, 0, 0, false, 0, false, 0, 0, 0, 0} #define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}} #define meshtastic_Nau7802Config_init_zero {0, 0} @@ -417,6 +444,14 @@ extern "C" { #define meshtastic_HealthMetrics_heart_bpm_tag 1 #define meshtastic_HealthMetrics_spO2_tag 2 #define meshtastic_HealthMetrics_temperature_tag 3 +#define meshtastic_HostMetrics_uptime_seconds_tag 1 +#define meshtastic_HostMetrics_freemem_bytes_tag 2 +#define meshtastic_HostMetrics_diskfree1_bytes_tag 3 +#define meshtastic_HostMetrics_diskfree2_bytes_tag 4 +#define meshtastic_HostMetrics_diskfree3_bytes_tag 5 +#define meshtastic_HostMetrics_load1_tag 6 +#define meshtastic_HostMetrics_load5_tag 7 +#define meshtastic_HostMetrics_load15_tag 8 #define meshtastic_Telemetry_time_tag 1 #define meshtastic_Telemetry_device_metrics_tag 2 #define meshtastic_Telemetry_environment_metrics_tag 3 @@ -424,6 +459,7 @@ extern "C" { #define meshtastic_Telemetry_power_metrics_tag 5 #define meshtastic_Telemetry_local_stats_tag 6 #define meshtastic_Telemetry_health_metrics_tag 7 +#define meshtastic_Telemetry_host_metrics_tag 8 #define meshtastic_Nau7802Config_zeroOffset_tag 1 #define meshtastic_Nau7802Config_calibrationFactor_tag 2 @@ -512,6 +548,18 @@ X(a, STATIC, OPTIONAL, FLOAT, temperature, 3) #define meshtastic_HealthMetrics_CALLBACK NULL #define meshtastic_HealthMetrics_DEFAULT NULL +#define meshtastic_HostMetrics_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, uptime_seconds, 1) \ +X(a, STATIC, SINGULAR, UINT64, freemem_bytes, 2) \ +X(a, STATIC, SINGULAR, UINT64, diskfree1_bytes, 3) \ +X(a, STATIC, OPTIONAL, UINT64, diskfree2_bytes, 4) \ +X(a, STATIC, OPTIONAL, UINT64, diskfree3_bytes, 5) \ +X(a, STATIC, SINGULAR, UINT32, load1, 6) \ +X(a, STATIC, SINGULAR, UINT32, load5, 7) \ +X(a, STATIC, SINGULAR, UINT32, load15, 8) +#define meshtastic_HostMetrics_CALLBACK NULL +#define meshtastic_HostMetrics_DEFAULT NULL + #define meshtastic_Telemetry_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, FIXED32, time, 1) \ X(a, STATIC, ONEOF, MESSAGE, (variant,device_metrics,variant.device_metrics), 2) \ @@ -519,7 +567,8 @@ X(a, STATIC, ONEOF, MESSAGE, (variant,environment_metrics,variant.environm X(a, STATIC, ONEOF, MESSAGE, (variant,air_quality_metrics,variant.air_quality_metrics), 4) \ X(a, STATIC, ONEOF, MESSAGE, (variant,power_metrics,variant.power_metrics), 5) \ X(a, STATIC, ONEOF, MESSAGE, (variant,local_stats,variant.local_stats), 6) \ -X(a, STATIC, ONEOF, MESSAGE, (variant,health_metrics,variant.health_metrics), 7) +X(a, STATIC, ONEOF, MESSAGE, (variant,health_metrics,variant.health_metrics), 7) \ +X(a, STATIC, ONEOF, MESSAGE, (variant,host_metrics,variant.host_metrics), 8) #define meshtastic_Telemetry_CALLBACK NULL #define meshtastic_Telemetry_DEFAULT NULL #define meshtastic_Telemetry_variant_device_metrics_MSGTYPE meshtastic_DeviceMetrics @@ -528,6 +577,7 @@ X(a, STATIC, ONEOF, MESSAGE, (variant,health_metrics,variant.health_metric #define meshtastic_Telemetry_variant_power_metrics_MSGTYPE meshtastic_PowerMetrics #define meshtastic_Telemetry_variant_local_stats_MSGTYPE meshtastic_LocalStats #define meshtastic_Telemetry_variant_health_metrics_MSGTYPE meshtastic_HealthMetrics +#define meshtastic_Telemetry_variant_host_metrics_MSGTYPE meshtastic_HostMetrics #define meshtastic_Nau7802Config_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, zeroOffset, 1) \ @@ -541,6 +591,7 @@ extern const pb_msgdesc_t meshtastic_PowerMetrics_msg; extern const pb_msgdesc_t meshtastic_AirQualityMetrics_msg; extern const pb_msgdesc_t meshtastic_LocalStats_msg; extern const pb_msgdesc_t meshtastic_HealthMetrics_msg; +extern const pb_msgdesc_t meshtastic_HostMetrics_msg; extern const pb_msgdesc_t meshtastic_Telemetry_msg; extern const pb_msgdesc_t meshtastic_Nau7802Config_msg; @@ -551,6 +602,7 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg; #define meshtastic_AirQualityMetrics_fields &meshtastic_AirQualityMetrics_msg #define meshtastic_LocalStats_fields &meshtastic_LocalStats_msg #define meshtastic_HealthMetrics_fields &meshtastic_HealthMetrics_msg +#define meshtastic_HostMetrics_fields &meshtastic_HostMetrics_msg #define meshtastic_Telemetry_fields &meshtastic_Telemetry_msg #define meshtastic_Nau7802Config_fields &meshtastic_Nau7802Config_msg @@ -560,6 +612,7 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg; #define meshtastic_DeviceMetrics_size 27 #define meshtastic_EnvironmentMetrics_size 113 #define meshtastic_HealthMetrics_size 11 +#define meshtastic_HostMetrics_size 62 #define meshtastic_LocalStats_size 60 #define meshtastic_Nau7802Config_size 16 #define meshtastic_PowerMetrics_size 30 From 60d2cb35e026040013e98c102761def6498d48b9 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 14 May 2025 18:55:27 -0500 Subject: [PATCH 10/21] Namespace --- test/test_mqtt/MQTT.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_mqtt/MQTT.cpp b/test/test_mqtt/MQTT.cpp index a297dc229..3cd56cfb6 100644 --- a/test/test_mqtt/MQTT.cpp +++ b/test/test_mqtt/MQTT.cpp @@ -310,7 +310,7 @@ void setUp(void) { moduleConfig.mqtt = meshtastic_ModuleConfig_MQTTConfig{.enabled = true, .map_reporting_enabled = true, .has_map_report_settings = true}; - mqtt.map_report_settings = meshtastic_ModuleConfig_MQTTConfig_MapReportSettings{ + mqtt.map_report_settings = meshtastic_ModuleConfig_MapReportSettings{ .position_precision = 14, .publish_interval_secs = 0, .should_report_location = true}; channelFile.channels[0] = meshtastic_Channel{ .index = 0, From ef9d0d7805a012cd48af90ff702ee7c082512628 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 14 May 2025 20:22:01 -0500 Subject: [PATCH 11/21] Go --- test/test_mqtt/MQTT.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_mqtt/MQTT.cpp b/test/test_mqtt/MQTT.cpp index 3cd56cfb6..c1f5da358 100644 --- a/test/test_mqtt/MQTT.cpp +++ b/test/test_mqtt/MQTT.cpp @@ -310,8 +310,8 @@ void setUp(void) { moduleConfig.mqtt = meshtastic_ModuleConfig_MQTTConfig{.enabled = true, .map_reporting_enabled = true, .has_map_report_settings = true}; - mqtt.map_report_settings = meshtastic_ModuleConfig_MapReportSettings{ - .position_precision = 14, .publish_interval_secs = 0, .should_report_location = true}; + moduleConfig.mqtt.map_report_settings = meshtastic_ModuleConfig_MapReportSettings{ + .publish_interval_secs = 0, .position_precision = 14, .should_report_location = true}; channelFile.channels[0] = meshtastic_Channel{ .index = 0, .has_settings = true, From 6bba17d463b9cf114b1db9bb420ad1ea075bd974 Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Thu, 15 May 2025 19:26:41 +1000 Subject: [PATCH 12/21] Add suppport for Quectel L80 (#6803) * Add suppport for Quectel L80 Another PMTK family chip, requires only a modification to the probe code. * Update support for L80 based on testing. --- src/gps/GPS.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index e234fdb4a..142241c43 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -1250,11 +1250,10 @@ GnssModel_t GPS::probe(int serialSpeed) // Close all NMEA sentences, valid for MTK3333 and MTK3339 platforms _serial_gps->write("$PMTK514,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*2E\r\n"); delay(20); - std::vector mtk = {{"L76B", "Quectel-L76B", GNSS_MODEL_MTK_L76B}, - {"PA1010D", "1010D", GNSS_MODEL_MTK_PA1010D}, - {"PA1616S", "1616S", GNSS_MODEL_MTK_PA1616S}, - {"LS20031", "MC-1513", GNSS_MODEL_MTK_L76B}, - {"L96", "Quectel-L96", GNSS_MODEL_MTK_L76B}}; + std::vector mtk = {{"L76B", "Quectel-L76B", GNSS_MODEL_MTK_L76B}, {"PA1010D", "1010D", GNSS_MODEL_MTK_PA1010D}, + {"PA1616S", "1616S", GNSS_MODEL_MTK_PA1616S}, {"LS20031", "MC-1513", GNSS_MODEL_MTK_L76B}, + {"L96", "Quectel-L96", GNSS_MODEL_MTK_L76B}, {"L80-R", "_3337_", GNSS_MODEL_MTK_L76B}, + {"L80", "_3339_", GNSS_MODEL_MTK_L76B}}; PROBE_FAMILY("MTK Family", "$PMTK605*31", mtk, 500); From c2d586216103192995d1059809ef213f38dc4592 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 15 May 2025 06:40:07 -0500 Subject: [PATCH 13/21] automated bumps (#6820) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- bin/org.meshtastic.meshtasticd.metainfo.xml | 3 +++ debian/changelog | 7 +++++-- version.properties | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bin/org.meshtastic.meshtasticd.metainfo.xml b/bin/org.meshtastic.meshtasticd.metainfo.xml index b98b54dd4..1a7ad284d 100644 --- a/bin/org.meshtastic.meshtasticd.metainfo.xml +++ b/bin/org.meshtastic.meshtasticd.metainfo.xml @@ -87,6 +87,9 @@ + + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.9 + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.8 diff --git a/debian/changelog b/debian/changelog index 8fce06c14..ae27bc3e9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -meshtasticd (2.6.8.0) UNRELEASED; urgency=medium +meshtasticd (2.6.9.0) UNRELEASED; urgency=medium [ Austin Lane ] * Initial packaging @@ -10,4 +10,7 @@ meshtasticd (2.6.8.0) UNRELEASED; urgency=medium [ ] * GitHub Actions Automatic version bump - -- Tue, 06 May 2025 01:32:49 +0000 + [ ] + * GitHub Actions Automatic version bump + + -- Thu, 15 May 2025 11:13:30 +0000 diff --git a/version.properties b/version.properties index bedba21b7..b0e960697 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 6 -build = 8 +build = 9 From 7d8f9c7f6df516d8c2561f3c3979581ab5209f47 Mon Sep 17 00:00:00 2001 From: Austin Date: Thu, 15 May 2025 07:40:46 -0400 Subject: [PATCH 14/21] Stop the madness! Run as a user (not root) (#6718) * Stop the madness! Run as a user (not root) * Trigger fsdir migration for < 2.6.9 --------- Co-authored-by: Ben Meadors --- .trunk/trunk.yaml | 1 - Dockerfile | 14 ++++-- alpine.Dockerfile | 11 ++++- bin/99-meshtasticd-udev.rules | 4 ++ bin/config-dist.yaml | 2 +- bin/meshtasticd.service | 7 +-- bin/native-install.sh | 2 +- debian/control | 6 ++- debian/meshtasticd.dirs | 3 +- debian/meshtasticd.install | 4 +- debian/meshtasticd.postinst | 79 ++++++++++++++++++++++++++++++ debian/meshtasticd.postrm | 41 ++++++++++++++++ debian/meshtasticd.udev | 4 ++ meshtasticd.spec.rpkg | 66 +++++++++++++++++++++++-- src/mesh/raspihttp/PiWebServer.cpp | 4 +- 15 files changed, 225 insertions(+), 23 deletions(-) create mode 100644 bin/99-meshtasticd-udev.rules create mode 100755 debian/meshtasticd.postinst create mode 100755 debian/meshtasticd.postrm create mode 100644 debian/meshtasticd.udev diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 4aa5527be..79bdf4778 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -13,7 +13,6 @@ lint: - trufflehog@3.88.29 - yamllint@1.37.1 - bandit@1.8.3 - - terrascan@1.19.9 - trivy@0.62.1 - taplo@0.9.3 - ruff@0.11.9 diff --git a/Dockerfile b/Dockerfile index 6c1b83653..e033b1bba 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,3 @@ -# trunk-ignore-all(terrascan/AC_DOCKER_0002): Known terrascan issue # trunk-ignore-all(trivy/DS002): We must run as root for this container # trunk-ignore-all(hadolint/DL3002): We must run as root for this container # trunk-ignore-all(hadolint/DL3008): Do not pin apt package versions @@ -38,6 +37,13 @@ RUN curl -L "https://github.com/meshtastic/web/releases/download/v$(cat /tmp/fir ##### PRODUCTION BUILD ############# FROM debian:bookworm-slim +LABEL org.opencontainers.image.title="Meshtastic" \ + org.opencontainers.image.description="Debian Meshtastic daemon and web interface" \ + org.opencontainers.image.url="https://meshtastic.org" \ + org.opencontainers.image.documentation="https://meshtastic.org/docs/" \ + org.opencontainers.image.authors="Meshtastic" \ + org.opencontainers.image.licenses="GPL-3.0-or-later" \ + org.opencontainers.image.source="https://github.com/meshtastic/firmware/" ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Etc/UTC @@ -54,7 +60,7 @@ RUN apt-get update && apt-get --no-install-recommends -y install \ && mkdir -p /etc/meshtasticd/ssl # Fetch compiled binary from the builder -COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/ +COPY --from=builder /tmp/firmware/release/meshtasticd /usr/bin/ COPY --from=builder /tmp/web /usr/share/meshtasticd/ # Copy config templates COPY ./bin/config.d /etc/meshtasticd/available.d @@ -65,8 +71,8 @@ VOLUME /var/lib/meshtasticd # Expose Meshtastic TCP API port from the host EXPOSE 4403 # Expose Meshtastic Web UI port from the host -EXPOSE 443 +EXPOSE 9443 -CMD [ "sh", "-cx", "meshtasticd -d /var/lib/meshtasticd" ] +CMD [ "sh", "-cx", "meshtasticd --fsdir=/var/lib/meshtasticd" ] HEALTHCHECK NONE diff --git a/alpine.Dockerfile b/alpine.Dockerfile index 350129040..bf7cad6d4 100644 --- a/alpine.Dockerfile +++ b/alpine.Dockerfile @@ -28,12 +28,19 @@ RUN bash ./bin/build-native.sh "$PIO_ENV" && \ # ##### PRODUCTION BUILD ############# FROM alpine:3.21 +LABEL org.opencontainers.image.title="Meshtastic" \ + org.opencontainers.image.description="Alpine Meshtastic daemon" \ + org.opencontainers.image.url="https://meshtastic.org" \ + org.opencontainers.image.documentation="https://meshtastic.org/docs/" \ + org.opencontainers.image.authors="Meshtastic" \ + org.opencontainers.image.licenses="GPL-3.0-or-later" \ + org.opencontainers.image.source="https://github.com/meshtastic/firmware/" # nosemgrep: dockerfile.security.last-user-is-root.last-user-is-root USER root RUN apk --no-cache add \ - libstdc++ libgpiod yaml-cpp libusb i2c-tools libuv \ + shadow libstdc++ libgpiod yaml-cpp libusb i2c-tools libuv \ libx11 libinput libxkbcommon \ && rm -rf /var/cache/apk/* \ && mkdir -p /var/lib/meshtasticd \ @@ -41,7 +48,7 @@ RUN apk --no-cache add \ && mkdir -p /etc/meshtasticd/ssl # Fetch compiled binary from the builder -COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/ +COPY --from=builder /tmp/firmware/release/meshtasticd /usr/bin/ # Copy config templates COPY ./bin/config.d /etc/meshtasticd/available.d diff --git a/bin/99-meshtasticd-udev.rules b/bin/99-meshtasticd-udev.rules new file mode 100644 index 000000000..69a468d7a --- /dev/null +++ b/bin/99-meshtasticd-udev.rules @@ -0,0 +1,4 @@ +# Set spidev ownership to 'spi' group. +SUBSYSTEM=="spidev", KERNEL=="spidev*", GROUP="spi", MODE="0660" +# Allow access to USB CH341 devices +SUBSYSTEM=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="5512", MODE="0666" diff --git a/bin/config-dist.yaml b/bin/config-dist.yaml index 9238d0e56..98c7696f0 100644 --- a/bin/config-dist.yaml +++ b/bin/config-dist.yaml @@ -188,7 +188,7 @@ Logging: # AsciiLogs: true # default if not specified is !isatty() on stdout Webserver: -# Port: 443 # Port for Webserver & Webservices +# Port: 9443 # Port for Webserver & Webservices # RootPath: /usr/share/meshtasticd/web # Root Dir of WebServer # SSLKey: /etc/meshtasticd/ssl/private_key.pem # Path to SSL Key, generated if not present # SSLCert: /etc/meshtasticd/ssl/certificate.pem # Path to SSL Certificate, generated if not present diff --git a/bin/meshtasticd.service b/bin/meshtasticd.service index 1e8ee98b8..63430bae8 100644 --- a/bin/meshtasticd.service +++ b/bin/meshtasticd.service @@ -5,10 +5,11 @@ StartLimitInterval=200 StartLimitBurst=5 [Service] -User=root -Group=root +AmbientCapabilities=CAP_NET_BIND_SERVICE +User=meshtasticd +Group=meshtasticd Type=simple -ExecStart=/usr/sbin/meshtasticd +ExecStart=/usr/bin/meshtasticd Restart=always RestartSec=3 diff --git a/bin/native-install.sh b/bin/native-install.sh index a8fcc29a6..18cd9205b 100755 --- a/bin/native-install.sh +++ b/bin/native-install.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -cp "release/meshtasticd_linux_$(uname -m)" /usr/sbin/meshtasticd +cp "release/meshtasticd_linux_$(uname -m)" /usr/bin/meshtasticd mkdir -p /etc/meshtasticd if [[ -f "/etc/meshtasticd/config.yaml" ]]; then cp bin/config-dist.yaml /etc/meshtasticd/config-upgrade.yaml diff --git a/debian/control b/debian/control index 9277f6f54..761383a5c 100644 --- a/debian/control +++ b/debian/control @@ -31,7 +31,9 @@ Rules-Requires-Root: no Package: meshtasticd Architecture: any -Depends: ${misc:Depends}, ${shlibs:Depends} +Depends: adduser, + ${misc:Depends}, + ${shlibs:Depends} Description: Meshtastic daemon for communicating with Meshtastic devices Meshtastic is an off-grid text communication platform that uses inexpensive - LoRa radios. \ No newline at end of file + LoRa radios. diff --git a/debian/meshtasticd.dirs b/debian/meshtasticd.dirs index 45a1ca3db..a667768b2 100644 --- a/debian/meshtasticd.dirs +++ b/debian/meshtasticd.dirs @@ -1,5 +1,6 @@ +var/lib/meshtasticd etc/meshtasticd etc/meshtasticd/config.d etc/meshtasticd/available.d usr/share/meshtasticd/web -etc/meshtasticd/ssl \ No newline at end of file +etc/meshtasticd/ssl diff --git a/debian/meshtasticd.install b/debian/meshtasticd.install index 6b6b5a361..3c68b42b1 100644 --- a/debian/meshtasticd.install +++ b/debian/meshtasticd.install @@ -1,8 +1,8 @@ -.pio/build/native-tft/meshtasticd usr/sbin +.pio/build/native-tft/meshtasticd usr/bin bin/config.yaml etc/meshtasticd bin/config.d/* etc/meshtasticd/available.d bin/meshtasticd.service lib/systemd/system -web/* usr/share/meshtasticd/web \ No newline at end of file +web/* usr/share/meshtasticd/web diff --git a/debian/meshtasticd.postinst b/debian/meshtasticd.postinst new file mode 100755 index 000000000..324865718 --- /dev/null +++ b/debian/meshtasticd.postinst @@ -0,0 +1,79 @@ +#!/bin/sh +# postinst script for meshtasticd +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure|reconfigure) + # create spi group (for udev rules) + # this group already exists on Raspberry Pi OS + getent group spi >/dev/null 2>/dev/null || addgroup --system spi + # create a meshtasticd group and user + getent passwd meshtasticd >/dev/null 2>/dev/null || adduser --system --home /var/lib/meshtasticd --no-create-home meshtasticd + getent group meshtasticd >/dev/null 2>/dev/null || addgroup --system meshtasticd + adduser meshtasticd meshtasticd >/dev/null 2>/dev/null + adduser meshtasticd spi >/dev/null 2>/dev/null + # add meshtasticd user to appropriate groups (if they exist) + getent group gpio >/dev/null 2>/dev/null && adduser meshtasticd gpio >/dev/null 2>/dev/null + getent group plugdev >/dev/null 2>/dev/null && adduser meshtasticd plugdev >/dev/null 2>/dev/null + getent group dialout >/dev/null 2>/dev/null && adduser meshtasticd dialout >/dev/null 2>/dev/null + getent group i2c >/dev/null 2>/dev/null && adduser meshtasticd i2c >/dev/null 2>/dev/null + getent group video >/dev/null 2>/dev/null && adduser meshtasticd video >/dev/null 2>/dev/null + getent group audio >/dev/null 2>/dev/null && adduser meshtasticd audio >/dev/null 2>/dev/null + getent group input >/dev/null 2>/dev/null && adduser meshtasticd input >/dev/null 2>/dev/null + + + # migrate /root/.portduino to /var/lib/meshtasticd/.portduino + # should only run once, upon upgrade from < 2.6.9 + if [ -n "$2" ] && dpkg --compare-versions "$2" lt 2.6.9; then + if [ -d /root/.portduino ] && [ ! -e /var/lib/meshtasticd/.portduino ]; then + cp -r /root/.portduino /var/lib/meshtasticd/.portduino + echo "Migrated meshtasticd VFS from /root/.portduino to /var/lib/meshtasticd/.portduino" + echo "meshtasticd now runs as the 'meshtasticd' user, not 'root'." + echo "See https://github.com/meshtastic/firmware/pull/6718 for details" + fi + fi + + if [ -d /var/lib/meshtasticd ]; then + chown -R meshtasticd:meshtasticd /var/lib/meshtasticd + fi + + if [ -d /etc/meshtasticd ]; then + chown -R meshtasticd:meshtasticd /etc/meshtasticd + fi + + if [ -d /usr/share/meshtasticd ]; then + chown -R meshtasticd:meshtasticd /usr/share/meshtasticd + fi + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/debian/meshtasticd.postrm b/debian/meshtasticd.postrm new file mode 100755 index 000000000..bb2c32a5b --- /dev/null +++ b/debian/meshtasticd.postrm @@ -0,0 +1,41 @@ +#!/bin/sh +# postrm script for meshtasticd +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `purge' +# * `upgrade' +# * `failed-upgrade' +# * `abort-install' +# * `abort-install' +# * `abort-upgrade' +# * `disappear' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + # Only remove /var/lib/meshtasticd on purge + if [ "${1}" = "purge" ] ; then + rm -rf /var/lib/meshtasticd + fi + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/debian/meshtasticd.udev b/debian/meshtasticd.udev new file mode 100644 index 000000000..69a468d7a --- /dev/null +++ b/debian/meshtasticd.udev @@ -0,0 +1,4 @@ +# Set spidev ownership to 'spi' group. +SUBSYSTEM=="spidev", KERNEL=="spidev*", GROUP="spi", MODE="0660" +# Allow access to USB CH341 devices +SUBSYSTEM=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="5512", MODE="0666" diff --git a/meshtasticd.spec.rpkg b/meshtasticd.spec.rpkg index 2d777bc76..eb4ab5ae7 100644 --- a/meshtasticd.spec.rpkg +++ b/meshtasticd.spec.rpkg @@ -10,6 +10,8 @@ # - https://docs.pagure.org/rpkg-util/v3/index.html # - https://docs.fedoraproject.org/en-US/packaging-guidelines/Versioning/ +%global meshtasticd_user meshtasticd + Name: meshtasticd # Version Ex: 2.5.19 Version: {{{ meshtastic_version }}} @@ -47,6 +49,8 @@ BuildRequires: pkgconfig(x11) BuildRequires: pkgconfig(libinput) BuildRequires: pkgconfig(xkbcommon-x11) +Requires: systemd-udev + %description Meshtastic daemon for controlling Meshtastic devices. Meshtastic is an off-grid text communication platform that uses inexpensive LoRa radios. @@ -63,15 +67,25 @@ gzip -dr web platformio run -e native-tft %install -mkdir -p %{buildroot}%{_sbindir} -install -m 0755 .pio/build/native-tft/program %{buildroot}%{_sbindir}/meshtasticd +# Install meshtasticd binary +mkdir -p %{buildroot}%{_bindir} +install -m 0755 .pio/build/native-tft/program %{buildroot}%{_bindir}/meshtasticd +# Install portduino VFS dir +install -p -d -m 0770 %{buildroot}%{_localstatedir}/lib/meshtasticd + +# Install udev rules +mkdir -p %{buildroot}%{_udevrulesdir} +install -m 0644 bin/99-meshtasticd-udev.rules %{buildroot}%{_udevrulesdir}/99-meshtasticd-udev.rules + +# Install config dirs mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd install -m 0644 bin/config-dist.yaml %{buildroot}%{_sysconfdir}/meshtasticd/config.yaml mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/config.d mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/available.d cp -r bin/config.d/* %{buildroot}%{_sysconfdir}/meshtasticd/available.d +# Install systemd service install -D -m 0644 bin/meshtasticd.service %{buildroot}%{_unitdir}/meshtasticd.service # Install the web files under /usr/share/meshtasticd/web @@ -80,10 +94,54 @@ cp -r web/* %{buildroot}%{_datadir}/meshtasticd/web # Install default SSL storage directory (for web) mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/ssl +%pre +# create spi group (for udev rules) +getent group spi > /dev/null || groupadd -r spi +# create a meshtasticd group and user +getent group %{meshtasticd_user} > /dev/null || groupadd -r %{meshtasticd_user} +getent passwd %{meshtasticd_user} > /dev/null || \ + useradd -r -d %{_localstatedir}/lib/meshtasticd -g %{meshtasticd_user} -G spi \ + -s /sbin/nologin -c "Meshtastic Daemon" %{meshtasticd_user} +# add meshtasticd user to appropriate groups (if they exist) +getent group gpio > /dev/null && usermod -a -G gpio %{meshtasticd_user} > /dev/null +getent group plugdev > /dev/null && usermod -a -G plugdev %{meshtasticd_user} > /dev/null +getent group dialout > /dev/null && usermod -a -G dialout %{meshtasticd_user} > /dev/null +getent group i2c > /dev/null && usermod -a -G i2c %{meshtasticd_user} > /dev/null +getent group video > /dev/null && usermod -a -G video %{meshtasticd_user} > /dev/null +getent group audio > /dev/null && usermod -a -G audio %{meshtasticd_user} > /dev/null +getent group input > /dev/null && usermod -a -G input %{meshtasticd_user} > /dev/null +exit 0 + +%triggerin -- meshtasticd < 2.6.9 +# migrate .portduino (if it exists and hasn’t already been copied) +if [ -d /root/.portduino ] && [ ! -e /var/lib/meshtasticd/.portduino ]; then + mkdir -p /var/lib/meshtasticd + cp -r /root/.portduino /var/lib/meshtasticd/.portduino + chown -R %{meshtasticd_user}:%{meshtasticd_user} \ + %{_localstatedir}/lib/meshtasticd || : + # Fix SELinux labels if present (no-op on non-SELinux systems) + restorecon -R /var/lib/meshtasticd/.portduino 2>/dev/null || : + echo "Migrated meshtasticd VFS from /root/.portduino to /var/lib/meshtasticd/.portduino" + echo "meshtasticd now runs as the 'meshtasticd' user, not 'root'." + echo "See https://github.com/meshtastic/firmware/pull/6718 for details" +fi + +%post +%systemd_post meshtasticd.service + +%preun +%systemd_preun meshtasticd.service + +%postun +%systemd_postun_with_restart meshtasticd.service + %files +%defattr(-,%{meshtasticd_user},%{meshtasticd_user}) %license LICENSE %doc README.md -%{_sbindir}/meshtasticd +%{_bindir}/meshtasticd +%dir %{_localstatedir}/lib/meshtasticd +%{_udevrulesdir}/99-meshtasticd-udev.rules %dir %{_sysconfdir}/meshtasticd %dir %{_sysconfdir}/meshtasticd/config.d %dir %{_sysconfdir}/meshtasticd/available.d @@ -96,4 +154,4 @@ mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/ssl %dir %{_sysconfdir}/meshtasticd/ssl %changelog -%autochangelog \ No newline at end of file +%autochangelog diff --git a/src/mesh/raspihttp/PiWebServer.cpp b/src/mesh/raspihttp/PiWebServer.cpp index 4fae0bc3d..7d3542e83 100644 --- a/src/mesh/raspihttp/PiWebServer.cpp +++ b/src/mesh/raspihttp/PiWebServer.cpp @@ -462,8 +462,8 @@ PiWebServerThread::PiWebServerThread() webservport = settingsMap[webserverport]; LOG_INFO("Use webserver port from yaml config %i ", webservport); } else { - LOG_INFO("Webserver port in yaml config set to 0, defaulting to port 443"); - webservport = 443; + LOG_INFO("Webserver port in yaml config set to 0, defaulting to port 9443"); + webservport = 9443; } // Web Content Service Instance From 1ef4caea05939c23cf3dfdedbf250bc0eff8b04e Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Thu, 15 May 2025 09:23:37 -0500 Subject: [PATCH 15/21] Host metrics (#6817) * Add std::string exec() function to PortduinoGlue for future work * MVP for HostMetrics module. * Fix compilation for other targets * Remove extra debug calls * Big numbers don't do well as INTs. * Add HostMetrics to config.yaml --- bin/config-dist.yaml | 6 ++ src/modules/Modules.cpp | 4 + src/modules/Telemetry/HostMetrics.cpp | 131 +++++++++++++++++++++++ src/modules/Telemetry/HostMetrics.h | 40 +++++++ src/platform/portduino/PortduinoGlue.cpp | 19 ++++ src/platform/portduino/PortduinoGlue.h | 7 +- 6 files changed, 205 insertions(+), 2 deletions(-) create mode 100644 src/modules/Telemetry/HostMetrics.cpp create mode 100644 src/modules/Telemetry/HostMetrics.h diff --git a/bin/config-dist.yaml b/bin/config-dist.yaml index 98c7696f0..2907e4aab 100644 --- a/bin/config-dist.yaml +++ b/bin/config-dist.yaml @@ -193,6 +193,12 @@ Webserver: # SSLKey: /etc/meshtasticd/ssl/private_key.pem # Path to SSL Key, generated if not present # SSLCert: /etc/meshtasticd/ssl/certificate.pem # Path to SSL Certificate, generated if not present + +HostMetrics: +# ReportInterval: 30 # Interval in minutes between HostMetrics report packets, or 0 for disabled +# Channel: 0 # channel to send Host Metrics over. Defaults to the primary channel. + + General: MaxNodes: 200 MaxMessageQueue: 100 diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp index 1f2b50057..fac2ca976 100644 --- a/src/modules/Modules.cpp +++ b/src/modules/Modules.cpp @@ -49,6 +49,7 @@ #endif #if ARCH_PORTDUINO #include "input/LinuxInputImpl.h" +#include "modules/Telemetry/HostMetrics.h" #if !MESHTASTIC_EXCLUDE_STOREFORWARD #include "modules/StoreForwardModule.h" #endif @@ -196,6 +197,9 @@ void setupModules() #if HAS_SCREEN && !MESHTASTIC_EXCLUDE_CANNEDMESSAGES cannedMessageModule = new CannedMessageModule(); #endif +#if ARCH_PORTDUINO + new HostMetricsModule(); +#endif #if HAS_TELEMETRY new DeviceTelemetryModule(); #endif diff --git a/src/modules/Telemetry/HostMetrics.cpp b/src/modules/Telemetry/HostMetrics.cpp new file mode 100644 index 000000000..655be4b25 --- /dev/null +++ b/src/modules/Telemetry/HostMetrics.cpp @@ -0,0 +1,131 @@ +#include "HostMetrics.h" +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "MeshService.h" +#if ARCH_PORTDUINO +#include "PortduinoGlue.h" +#include +#endif + +int32_t HostMetricsModule::runOnce() +{ +#if ARCH_PORTDUINO + if (settingsMap[hostMetrics_interval] == 0) { + return disable(); + } else { + sendMetrics(); + return 60 * 1000 * settingsMap[hostMetrics_interval]; + } +#else + return disable(); +#endif +} + +bool HostMetricsModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t) +{ + // Don't worry about storing telemetry in NodeDB if we're a repeater + if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) + return false; + + if (t->which_variant == meshtastic_Telemetry_host_metrics_tag) { +#ifdef DEBUG_PORT + const char *sender = getSenderShortName(mp); + + LOG_INFO("(Received Host Metrics from %s): uptime=%u, diskfree=%lu, memory free=%lu, load=%04.2f, %04.2f, %04.2f", sender, + t->variant.host_metrics.uptime_seconds, t->variant.host_metrics.diskfree1_bytes, + t->variant.host_metrics.freemem_bytes, static_cast(t->variant.host_metrics.load1) / 100, + static_cast(t->variant.host_metrics.load5) / 100, + static_cast(t->variant.host_metrics.load15) / 100); +#endif + } + return false; // Let others look at this message also if they want +} + +/* +meshtastic_MeshPacket *HostMetricsModule::allocReply() +{ + if (currentRequest) { + auto req = *currentRequest; + const auto &p = req.decoded; + meshtastic_Telemetry scratch; + meshtastic_Telemetry *decoded = NULL; + memset(&scratch, 0, sizeof(scratch)); + if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, &meshtastic_HostMetrics_msg, &scratch)) { + decoded = &scratch; + } else { + LOG_ERROR("Error decoding HostMetrics module!"); + return NULL; + } + // Check for a request for device metrics + if (decoded->which_variant == meshtastic_Telemetry_host_metrics_tag) { + LOG_INFO("Device telemetry reply to request"); + return allocDataProtobuf(getHostMetrics()); + } + } + return NULL; +} + */ + +#if ARCH_PORTDUINO +meshtastic_Telemetry HostMetricsModule::getHostMetrics() +{ + std::string file_line; + meshtastic_Telemetry t = meshtastic_HostMetrics_init_zero; + t.which_variant = meshtastic_Telemetry_host_metrics_tag; + + if (access("/proc/uptime", R_OK) == 0) { + std::ifstream proc_uptime("/proc/uptime"); + if (proc_uptime.is_open()) { + std::getline(proc_uptime, file_line, ' '); + proc_uptime.close(); + t.variant.host_metrics.uptime_seconds = stoul(file_line); + } + } + + std::filesystem::space_info root = std::filesystem::space("/"); + t.variant.host_metrics.diskfree1_bytes = root.available; + + if (access("/proc/meminfo", R_OK) == 0) { + std::ifstream proc_meminfo("/proc/meminfo"); + if (proc_meminfo.is_open()) { + do { + std::getline(proc_meminfo, file_line); + } while (file_line.find("MemAvailable") == std::string::npos); + proc_meminfo.close(); + t.variant.host_metrics.freemem_bytes = stoull(file_line.substr(file_line.find_first_of("0123456789"))) * 1024; + } + } + if (access("/proc/loadavg", R_OK) == 0) { + std::ifstream proc_loadavg("/proc/loadavg"); + if (proc_loadavg.is_open()) { + std::getline(proc_loadavg, file_line, ' '); + t.variant.host_metrics.load1 = stof(file_line) * 100; + std::getline(proc_loadavg, file_line, ' '); + t.variant.host_metrics.load5 = stof(file_line) * 100; + std::getline(proc_loadavg, file_line, ' '); + t.variant.host_metrics.load15 = stof(file_line) * 100; + proc_loadavg.close(); + } + } + + return t; +} + +bool HostMetricsModule::sendMetrics() +{ + meshtastic_Telemetry telemetry = getHostMetrics(); + LOG_INFO("Send: uptime=%u, diskfree=%lu, memory free=%lu, load=%04.2f, %04.2f, %04.2f", + telemetry.variant.host_metrics.uptime_seconds, telemetry.variant.host_metrics.diskfree1_bytes, + telemetry.variant.host_metrics.freemem_bytes, static_cast(telemetry.variant.host_metrics.load1) / 100, + static_cast(telemetry.variant.host_metrics.load5) / 100, + static_cast(telemetry.variant.host_metrics.load15) / 100); + + meshtastic_MeshPacket *p = allocDataProtobuf(telemetry); + p->to = NODENUM_BROADCAST; + p->decoded.want_response = false; + p->priority = meshtastic_MeshPacket_Priority_BACKGROUND; + p->channel = settingsMap[hostMetrics_channel]; + LOG_INFO("Send packet to mesh"); + service->sendToMesh(p, RX_SRC_LOCAL, true); + return true; +} +#endif \ No newline at end of file diff --git a/src/modules/Telemetry/HostMetrics.h b/src/modules/Telemetry/HostMetrics.h new file mode 100644 index 000000000..99ee631c1 --- /dev/null +++ b/src/modules/Telemetry/HostMetrics.h @@ -0,0 +1,40 @@ +#pragma once +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "ProtobufModule.h" + +class HostMetricsModule : private concurrency::OSThread, public ProtobufModule +{ + CallbackObserver nodeStatusObserver = + CallbackObserver(this, &HostMetricsModule::handleStatusUpdate); + + public: + HostMetricsModule() + : concurrency::OSThread("HostMetrics"), + ProtobufModule("HostMetrics", meshtastic_PortNum_TELEMETRY_APP, &meshtastic_Telemetry_msg) + { + uptimeWrapCount = 0; + uptimeLastMs = millis(); + nodeStatusObserver.observe(&nodeStatus->onNewStatus); + setIntervalFromNow(setStartDelay()); // Wait until NodeInfo is sent + } + virtual bool wantUIFrame() { return false; } + + protected: + /** Called to handle a particular incoming message + @return true if you've guaranteed you've handled this message and no other handlers should be considered for it + */ + virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *p) override; + // virtual meshtastic_MeshPacket *allocReply() override; + virtual int32_t runOnce() override; + /** + * Send our Telemetry into the mesh + */ + bool sendMetrics(); + + private: + meshtastic_Telemetry getHostMetrics(); + + uint32_t lastSentToMesh = 0; + uint32_t uptimeWrapCount; + uint32_t uptimeLastMs; +}; \ No newline at end of file diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index 4b96e662a..c6aa30629 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -600,6 +600,11 @@ bool loadConfig(const char *configPath) (yamlConfig["Webserver"]["SSLCert"]).as("/etc/meshtasticd/ssl/certificate.pem"); } + if (yamlConfig["HostMetrics"]) { + settingsMap[hostMetrics_channel] = (yamlConfig["HostMetrics"]["Channel"]).as(0); + settingsMap[hostMetrics_interval] = (yamlConfig["HostMetrics"]["ReportInterval"]).as(0); + } + if (yamlConfig["General"]) { settingsMap[maxnodes] = (yamlConfig["General"]["MaxNodes"]).as(200); settingsMap[maxtophone] = (yamlConfig["General"]["MaxMessageQueue"]).as(100); @@ -650,4 +655,18 @@ bool MAC_from_string(std::string mac_str, uint8_t *dmac) } else { return false; } +} + +std::string exec(const char *cmd) +{ // https://stackoverflow.com/a/478960 + std::array buffer; + std::string result; + std::unique_ptr pipe(popen(cmd, "r"), pclose); + if (!pipe) { + throw std::runtime_error("popen() failed!"); + } + while (fgets(buffer.data(), static_cast(buffer.size()), pipe.get()) != nullptr) { + result += buffer.data(); + } + return result; } \ No newline at end of file diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index 6393d7294..0cf0201aa 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -100,7 +100,9 @@ enum configNames { ascii_logs, config_directory, available_directory, - mac_address + mac_address, + hostMetrics_interval, + hostMetrics_channel }; enum { no_screen, x11, fb, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9486, ili9488, hx8357d }; enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 }; @@ -114,4 +116,5 @@ int initGPIOPin(int pinNum, std::string gpioChipname, int line); bool loadConfig(const char *configPath); static bool ends_with(std::string_view str, std::string_view suffix); void getMacAddr(uint8_t *dmac); -bool MAC_from_string(std::string mac_str, uint8_t *dmac); \ No newline at end of file +bool MAC_from_string(std::string mac_str, uint8_t *dmac); +std::string exec(const char *cmd); \ No newline at end of file From 066609a7189163f607fee5966f223526c30bd7d1 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Thu, 15 May 2025 21:29:08 -0500 Subject: [PATCH 16/21] Remove incomplete compass boot calibration (#6825) The made it in from testing unintentionally. --- src/main.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 452cb3526..1e46d9db1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1300,10 +1300,6 @@ void setup() LOG_DEBUG("Free heap : %7d bytes", ESP.getFreeHeap()); LOG_DEBUG("Free PSRAM : %7d bytes", ESP.getFreePsram()); #endif -#if !defined(ARCH_STM32WL) - if (accelerometerThread) - accelerometerThread->calibrate(30); -#endif } #endif From 3398a52a346263ff88a441e325d549242691aae7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 17 May 2025 06:15:44 -0500 Subject: [PATCH 17/21] Update meshtastic/device-ui digest to 55f7152 (#6830) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index b78ecdc1a..d5a954a80 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,7 @@ lib_deps = [device-ui_base] lib_deps = # renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master - https://github.com/meshtastic/device-ui/archive/7dee10ad31a0c6ea04880cba399e240be743d752.zip + https://github.com/meshtastic/device-ui/archive/55f71527f3137ed4eabc258498d5c6ad9f610674.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From a50a94150aba14aaba1639412c535e8f6e99a4ad Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 17 May 2025 10:44:02 -0500 Subject: [PATCH 18/21] [create-pull-request] automated change (#6834) Co-authored-by: jp-bennett <5630967+jp-bennett@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/telemetry.pb.h | 27 ++++++++++++-------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/protobufs b/protobufs index 4eb0aebae..475694e62 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 4eb0aebaef1304a5516b6fa864cb4c55daed9147 +Subproject commit 475694e62b0fdac3469abc15c6d66d05fc9ad69a diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index 1c5eb4843..4cce7ca33 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -89,7 +89,9 @@ typedef enum _meshtastic_TelemetrySensorType { /* RAKWireless RAK12035 Soil Moisture Sensor Module */ meshtastic_TelemetrySensorType_RAK12035 = 37, /* MAX17261 lipo battery gauge */ - meshtastic_TelemetrySensorType_MAX17261 = 38 + meshtastic_TelemetrySensorType_MAX17261 = 38, + /* PCT2075 Temperature Sensor */ + meshtastic_TelemetrySensorType_PCT2075 = 39 } meshtastic_TelemetrySensorType; /* Struct definitions */ @@ -310,6 +312,9 @@ typedef struct _meshtastic_HostMetrics { uint16_t load5; /* Host system fifteen minute load in 1/100ths */ uint16_t load15; + /* Optional User-provided string for arbitrary host system information + that doesn't make sense as a dedicated entry. */ + pb_callback_t user_string; } meshtastic_HostMetrics; /* Types of Measurements the telemetry module is equipped to handle */ @@ -350,8 +355,8 @@ extern "C" { /* Helper constants for enums */ #define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET -#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_MAX17261 -#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_MAX17261+1)) +#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_PCT2075 +#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_PCT2075+1)) @@ -370,7 +375,7 @@ extern "C" { #define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_HealthMetrics_init_default {false, 0, false, 0, false, 0} -#define meshtastic_HostMetrics_init_default {0, 0, 0, false, 0, false, 0, 0, 0, 0} +#define meshtastic_HostMetrics_init_default {0, 0, 0, false, 0, false, 0, 0, 0, 0, {{NULL}, NULL}} #define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}} #define meshtastic_Nau7802Config_init_default {0, 0} #define meshtastic_DeviceMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0} @@ -379,7 +384,7 @@ extern "C" { #define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_HealthMetrics_init_zero {false, 0, false, 0, false, 0} -#define meshtastic_HostMetrics_init_zero {0, 0, 0, false, 0, false, 0, 0, 0, 0} +#define meshtastic_HostMetrics_init_zero {0, 0, 0, false, 0, false, 0, 0, 0, 0, {{NULL}, NULL}} #define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}} #define meshtastic_Nau7802Config_init_zero {0, 0} @@ -452,6 +457,7 @@ extern "C" { #define meshtastic_HostMetrics_load1_tag 6 #define meshtastic_HostMetrics_load5_tag 7 #define meshtastic_HostMetrics_load15_tag 8 +#define meshtastic_HostMetrics_user_string_tag 9 #define meshtastic_Telemetry_time_tag 1 #define meshtastic_Telemetry_device_metrics_tag 2 #define meshtastic_Telemetry_environment_metrics_tag 3 @@ -556,8 +562,9 @@ X(a, STATIC, OPTIONAL, UINT64, diskfree2_bytes, 4) \ X(a, STATIC, OPTIONAL, UINT64, diskfree3_bytes, 5) \ X(a, STATIC, SINGULAR, UINT32, load1, 6) \ X(a, STATIC, SINGULAR, UINT32, load5, 7) \ -X(a, STATIC, SINGULAR, UINT32, load15, 8) -#define meshtastic_HostMetrics_CALLBACK NULL +X(a, STATIC, SINGULAR, UINT32, load15, 8) \ +X(a, CALLBACK, OPTIONAL, STRING, user_string, 9) +#define meshtastic_HostMetrics_CALLBACK pb_default_field_callback #define meshtastic_HostMetrics_DEFAULT NULL #define meshtastic_Telemetry_FIELDLIST(X, a) \ @@ -607,16 +614,16 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg; #define meshtastic_Nau7802Config_fields &meshtastic_Nau7802Config_msg /* Maximum encoded size of messages (where known) */ -#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size +/* meshtastic_HostMetrics_size depends on runtime parameters */ +/* meshtastic_Telemetry_size depends on runtime parameters */ +#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_EnvironmentMetrics_size #define meshtastic_AirQualityMetrics_size 78 #define meshtastic_DeviceMetrics_size 27 #define meshtastic_EnvironmentMetrics_size 113 #define meshtastic_HealthMetrics_size 11 -#define meshtastic_HostMetrics_size 62 #define meshtastic_LocalStats_size 60 #define meshtastic_Nau7802Config_size 16 #define meshtastic_PowerMetrics_size 30 -#define meshtastic_Telemetry_size 120 #ifdef __cplusplus } /* extern "C" */ From 5b312ab9175402d41cafe1c0a29f4c6a45f8c3a2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 17 May 2025 12:29:18 -0500 Subject: [PATCH 19/21] [create-pull-request] automated change (#6836) Co-authored-by: jp-bennett <5630967+jp-bennett@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/telemetry.pb.cpp | 4 ++-- src/mesh/generated/meshtastic/telemetry.pb.h | 17 +++++++++-------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/protobufs b/protobufs index 475694e62..d8b709aa5 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 475694e62b0fdac3469abc15c6d66d05fc9ad69a +Subproject commit d8b709aa5da85959a80a06a6624761678a96f9c0 diff --git a/src/mesh/generated/meshtastic/telemetry.pb.cpp b/src/mesh/generated/meshtastic/telemetry.pb.cpp index b54cbb00e..345d7a157 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.cpp +++ b/src/mesh/generated/meshtastic/telemetry.pb.cpp @@ -24,10 +24,10 @@ PB_BIND(meshtastic_LocalStats, meshtastic_LocalStats, AUTO) PB_BIND(meshtastic_HealthMetrics, meshtastic_HealthMetrics, AUTO) -PB_BIND(meshtastic_HostMetrics, meshtastic_HostMetrics, AUTO) +PB_BIND(meshtastic_HostMetrics, meshtastic_HostMetrics, 2) -PB_BIND(meshtastic_Telemetry, meshtastic_Telemetry, AUTO) +PB_BIND(meshtastic_Telemetry, meshtastic_Telemetry, 2) PB_BIND(meshtastic_Nau7802Config, meshtastic_Nau7802Config, AUTO) diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index 4cce7ca33..4071c611e 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -314,7 +314,8 @@ typedef struct _meshtastic_HostMetrics { uint16_t load15; /* Optional User-provided string for arbitrary host system information that doesn't make sense as a dedicated entry. */ - pb_callback_t user_string; + bool has_user_string; + char user_string[200]; } meshtastic_HostMetrics; /* Types of Measurements the telemetry module is equipped to handle */ @@ -375,7 +376,7 @@ extern "C" { #define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_HealthMetrics_init_default {false, 0, false, 0, false, 0} -#define meshtastic_HostMetrics_init_default {0, 0, 0, false, 0, false, 0, 0, 0, 0, {{NULL}, NULL}} +#define meshtastic_HostMetrics_init_default {0, 0, 0, false, 0, false, 0, 0, 0, 0, false, ""} #define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}} #define meshtastic_Nau7802Config_init_default {0, 0} #define meshtastic_DeviceMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0} @@ -384,7 +385,7 @@ extern "C" { #define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0} #define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_HealthMetrics_init_zero {false, 0, false, 0, false, 0} -#define meshtastic_HostMetrics_init_zero {0, 0, 0, false, 0, false, 0, 0, 0, 0, {{NULL}, NULL}} +#define meshtastic_HostMetrics_init_zero {0, 0, 0, false, 0, false, 0, 0, 0, 0, false, ""} #define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}} #define meshtastic_Nau7802Config_init_zero {0, 0} @@ -563,8 +564,8 @@ X(a, STATIC, OPTIONAL, UINT64, diskfree3_bytes, 5) \ X(a, STATIC, SINGULAR, UINT32, load1, 6) \ X(a, STATIC, SINGULAR, UINT32, load5, 7) \ X(a, STATIC, SINGULAR, UINT32, load15, 8) \ -X(a, CALLBACK, OPTIONAL, STRING, user_string, 9) -#define meshtastic_HostMetrics_CALLBACK pb_default_field_callback +X(a, STATIC, OPTIONAL, STRING, user_string, 9) +#define meshtastic_HostMetrics_CALLBACK NULL #define meshtastic_HostMetrics_DEFAULT NULL #define meshtastic_Telemetry_FIELDLIST(X, a) \ @@ -614,16 +615,16 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg; #define meshtastic_Nau7802Config_fields &meshtastic_Nau7802Config_msg /* Maximum encoded size of messages (where known) */ -/* meshtastic_HostMetrics_size depends on runtime parameters */ -/* meshtastic_Telemetry_size depends on runtime parameters */ -#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_EnvironmentMetrics_size +#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size #define meshtastic_AirQualityMetrics_size 78 #define meshtastic_DeviceMetrics_size 27 #define meshtastic_EnvironmentMetrics_size 113 #define meshtastic_HealthMetrics_size 11 +#define meshtastic_HostMetrics_size 264 #define meshtastic_LocalStats_size 60 #define meshtastic_Nau7802Config_size 16 #define meshtastic_PowerMetrics_size 30 +#define meshtastic_Telemetry_size 272 #ifdef __cplusplus } /* extern "C" */ From 61e4eb12e63db87d9f7839d29f5042d329b8e32f Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sat, 17 May 2025 14:02:39 -0500 Subject: [PATCH 20/21] Use the _init_zero macro correctly for HostMetrics (#6837) --- src/modules/Telemetry/HostMetrics.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/Telemetry/HostMetrics.cpp b/src/modules/Telemetry/HostMetrics.cpp index 655be4b25..d1e5bdd00 100644 --- a/src/modules/Telemetry/HostMetrics.cpp +++ b/src/modules/Telemetry/HostMetrics.cpp @@ -69,8 +69,9 @@ meshtastic_MeshPacket *HostMetricsModule::allocReply() meshtastic_Telemetry HostMetricsModule::getHostMetrics() { std::string file_line; - meshtastic_Telemetry t = meshtastic_HostMetrics_init_zero; + meshtastic_Telemetry t = meshtastic_Telemetry_init_zero; t.which_variant = meshtastic_Telemetry_host_metrics_tag; + t.variant.host_metrics = meshtastic_HostMetrics_init_zero; if (access("/proc/uptime", R_OK) == 0) { std::ifstream proc_uptime("/proc/uptime"); From b2d81b740f2e5556ad2d76d0f01a60fb769d4a84 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 18 May 2025 21:11:02 +1000 Subject: [PATCH 21/21] Update dorny/test-reporter action to v2.1.0 (#6833) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/test_native.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_native.yml b/.github/workflows/test_native.yml index c3643dcbd..536d93665 100644 --- a/.github/workflows/test_native.yml +++ b/.github/workflows/test_native.yml @@ -143,7 +143,7 @@ jobs: merge-multiple: true - name: Test Report - uses: dorny/test-reporter@v2.0.0 + uses: dorny/test-reporter@v2.1.0 with: name: PlatformIO Tests path: testreport.xml