Compare commits

...

17 Commits

Author SHA1 Message Date
Jonathan Bennett
1f0ef2498a Don't reboot node simply for a StatusMessage config update 2026-01-20 18:10:40 -06:00
Jonathan Bennett
84cd870323 Trunk 2026-01-20 10:42:23 -06:00
Jonathan Bennett
2eda145a56 Merge branch 'develop' into status-message 2026-01-20 10:34:24 -06:00
github-actions[bot]
eefc08087d Update protobufs (#9371)
Co-authored-by: jp-bennett <5630967+jp-bennett@users.noreply.github.com>
2026-01-20 10:29:11 -06:00
Andrew Yong
fb6d199d36 feat: Add Russell, a board designed to go Up! on a balloon (#9079)
Hardware repository: https://github.com/Meshtastic-Malaysia/russell
- Designed to mount on an ER34615/IFR32700 cell
- RAK3172 STM32WLE5CCU6 MCU + integrated SX1262 LoRa
- CDtop CD-PA1010D GPS
- Bosch Sensortec BME280 sensor
- Consonance CN3158 LiFePO4 solar charger

Signed-off-by: Andrew Yong <me@ndoo.sg>
2026-01-20 06:38:04 -06:00
Ben Meadors
7d4600f8c2 Merge branch 'master' into develop 2026-01-19 12:13:52 -06:00
Ben Meadors
ff50ba4002 Remove bsec from OG ESP32 to fix DRAM overflow 2026-01-19 12:12:14 -06:00
github-actions[bot]
5c401b8e34 Update protobufs (#9362)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-01-19 12:11:13 -06:00
Ben Meadors
c96ebf15fd Merge remote-tracking branch 'origin/master' into develop 2026-01-19 07:57:36 -06:00
github-actions[bot]
3e4239daf8 Upgrade trunk (#9330)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-01-19 07:22:27 -06:00
Ben Meadors
ab97c0126f Merge pull request #9355 from meshtastic/fix-bme
Untangle some BME680 ifdef spaghetti
2026-01-19 07:21:37 -06:00
github-actions[bot]
d34d694731 Update protobufs (#9360)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-01-19 06:21:01 -06:00
renovate[bot]
caa6ec0e8a Update meshtastic/device-ui digest to 3480b73 (#9353)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-19 14:28:05 +11:00
Jonathan Bennett
2f821ca267 Merge branch 'develop' into status-message 2026-01-18 15:20:57 -06:00
Jonathan Bennett
be8506857c Add StatusMessage module and config overrides 2026-01-18 15:15:31 -06:00
Jonathan Bennett
afbd9e2180 Filter BLE updates that don't change pairing status (#9333) 2026-01-16 13:52:04 -06:00
Ben Meadors
64116cd0d3 Meshtastic OTA (moar) (#9327)
* Initial commit of combined BLE and WiFi OTA

* Incorporate ota_hash in AdminMessage protobuf

* OTA protobuf changes

* Trunk fmt

* Partition header check for OTA type

* Guards

* Guards

* Derp

* Missed one

---------

Co-authored-by: Jake-B <jake-b@users.noreply.github.com>
2026-01-15 14:36:36 -06:00
29 changed files with 500 additions and 65 deletions

View File

@@ -9,14 +9,14 @@ plugins:
lint:
enabled:
- checkov@3.2.497
- renovate@42.81.8
- renovate@42.84.2
- prettier@3.8.0
- trufflehog@3.92.4
- trufflehog@3.92.5
- yamllint@1.38.0
- bandit@1.9.2
- bandit@1.9.3
- trivy@0.68.2
- taplo@0.10.0
- ruff@0.14.11
- ruff@0.14.13
- isort@7.0.0
- markdownlint@0.47.0
- oxipng@10.0.0
@@ -26,7 +26,7 @@ lint:
- hadolint@2.14.0
- shfmt@3.6.0
- shellcheck@0.11.0
- black@25.12.0
- black@26.1.0
- git-diff-check
- gitleaks@8.30.0
- clang-format@16.0.3

View File

@@ -119,7 +119,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/5a870c623a4e9ab7a7abe3d02950536f107d1a31.zip
https://github.com/meshtastic/device-ui/archive/3480b731d28b10d73414cf0dd7975bff745de8cf.zip
; Common libs for environmental measurements in telemetry module
[environmental_base]
@@ -212,3 +212,30 @@ lib_deps =
sensirion/Sensirion Core@0.7.2
# renovate: datasource=custom.pio depName=Sensirion I2C SCD4x packageName=sensirion/library/Sensirion I2C SCD4x
sensirion/Sensirion I2C SCD4x@1.1.0
; Same as environmental_extra but without BSEC (saves ~3.5KB DRAM for original ESP32 targets)
[environmental_extra_no_bsec]
lib_deps =
# renovate: datasource=custom.pio depName=Adafruit BMP3XX packageName=adafruit/library/Adafruit BMP3XX Library
adafruit/Adafruit BMP3XX Library@2.1.6
# renovate: datasource=custom.pio depName=Adafruit MAX1704X packageName=adafruit/library/Adafruit MAX1704X
adafruit/Adafruit MAX1704X@1.0.3
# renovate: datasource=custom.pio depName=Adafruit SHTC3 packageName=adafruit/library/Adafruit SHTC3 Library
adafruit/Adafruit SHTC3 Library@1.0.2
# renovate: datasource=custom.pio depName=Adafruit LPS2X packageName=adafruit/library/Adafruit LPS2X
adafruit/Adafruit LPS2X@2.0.6
# renovate: datasource=custom.pio depName=Adafruit SHT31 packageName=adafruit/library/Adafruit SHT31 Library
adafruit/Adafruit SHT31 Library@2.2.2
# renovate: datasource=custom.pio depName=Adafruit VEML7700 packageName=adafruit/library/Adafruit VEML7700 Library
adafruit/Adafruit VEML7700 Library@2.1.6
# renovate: datasource=custom.pio depName=Adafruit SHT4x packageName=adafruit/library/Adafruit SHT4x Library
adafruit/Adafruit SHT4x Library@1.0.5
# renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6
# renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001
closedcube/ClosedCube OPT3001@1.1.2
# renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master
https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip
# renovate: datasource=custom.pio depName=Sensirion Core packageName=sensirion/library/Sensirion Core
sensirion/Sensirion Core@0.7.2
# renovate: datasource=custom.pio depName=Sensirion I2C SCD4x packageName=sensirion/library/Sensirion I2C SCD4x
sensirion/Sensirion I2C SCD4x@1.1.0

View File

@@ -105,6 +105,43 @@ NRF52Bluetooth *nrf52Bluetooth = nullptr;
#include <string>
#endif
#ifdef ARCH_ESP32
#ifdef DEBUG_PARTITION_TABLE
#include "esp_partition.h"
void printPartitionTable()
{
printf("\n--- Partition Table ---\n");
// Print Column Headers
printf("| %-16s | %-4s | %-7s | %-10s | %-10s |\n", "Label", "Type", "Subtype", "Offset", "Size");
printf("|------------------|------|---------|------------|------------|\n");
// Create an iterator to find ALL partitions (Type ANY, Subtype ANY)
esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL);
// Loop through the iterator
if (it != NULL) {
do {
const esp_partition_t *part = esp_partition_get(it);
// Print details: Label, Type (Hex), Subtype (Hex), Offset (Hex), Size (Hex)
printf("| %-16s | 0x%02x | 0x%02x | 0x%08x | 0x%08x |\n", part->label, part->type, part->subtype, part->address,
part->size);
// Move to next partition
it = esp_partition_next(it);
} while (it != NULL);
// Release the iterator memory
esp_partition_iterator_release(it);
} else {
printf("No partitions found.\n");
}
printf("-----------------------\n");
}
#endif // DEBUG_PARTITION_TABLE
#endif // ARCH_ESP32
#if HAS_BUTTON || defined(ARCH_PORTDUINO)
#include "input/ButtonThread.h"
@@ -648,7 +685,11 @@ void setup()
sensor_detected = true;
#endif
}
#ifdef ARCH_ESP32
#ifdef DEBUG_PARTITION_TABLE
printPartitionTable();
#endif
#endif // ARCH_ESP32
#ifdef ARCH_ESP32
// Don't init display if we don't have one or we are waking headless due to a timer event
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER) {

View File

@@ -1410,6 +1410,15 @@ void NodeDB::loadFromDisk()
if (portduino_config.has_configDisplayMode) {
config.display.displaymode = (_meshtastic_Config_DisplayConfig_DisplayMode)portduino_config.configDisplayMode;
}
if (portduino_config.has_statusMessage) {
moduleConfig.has_statusmessage = true;
strncpy(moduleConfig.statusmessage.node_status, portduino_config.statusMessage.c_str(),
sizeof(moduleConfig.statusmessage.node_status));
moduleConfig.statusmessage.node_status[sizeof(moduleConfig.statusmessage.node_status) - 1] = '\0';
}
if (portduino_config.enable_UDP) {
config.network.enabled_protocols = true;
}
#endif
}
@@ -1510,6 +1519,7 @@ bool NodeDB::saveToDiskNoRetry(int saveWhat)
moduleConfig.has_ambient_lighting = true;
moduleConfig.has_audio = true;
moduleConfig.has_paxcounter = true;
moduleConfig.has_statusmessage = true;
success &=
saveProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, &meshtastic_LocalModuleConfig_msg, &moduleConfig);

View File

@@ -77,7 +77,9 @@ typedef enum _meshtastic_AdminMessage_ModuleConfigType {
/* TODO: REPLACE */
meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG = 11,
/* TODO: REPLACE */
meshtastic_AdminMessage_ModuleConfigType_PAXCOUNTER_CONFIG = 12
meshtastic_AdminMessage_ModuleConfigType_PAXCOUNTER_CONFIG = 12,
/* TODO: REPLACE */
meshtastic_AdminMessage_ModuleConfigType_STATUSMESSAGE_CONFIG = 13
} meshtastic_AdminMessage_ModuleConfigType;
typedef enum _meshtastic_AdminMessage_BackupLocation {
@@ -323,8 +325,8 @@ extern "C" {
#define _meshtastic_AdminMessage_ConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ConfigType)(meshtastic_AdminMessage_ConfigType_DEVICEUI_CONFIG+1))
#define _meshtastic_AdminMessage_ModuleConfigType_MIN meshtastic_AdminMessage_ModuleConfigType_MQTT_CONFIG
#define _meshtastic_AdminMessage_ModuleConfigType_MAX meshtastic_AdminMessage_ModuleConfigType_PAXCOUNTER_CONFIG
#define _meshtastic_AdminMessage_ModuleConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ModuleConfigType)(meshtastic_AdminMessage_ModuleConfigType_PAXCOUNTER_CONFIG+1))
#define _meshtastic_AdminMessage_ModuleConfigType_MAX meshtastic_AdminMessage_ModuleConfigType_STATUSMESSAGE_CONFIG
#define _meshtastic_AdminMessage_ModuleConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ModuleConfigType)(meshtastic_AdminMessage_ModuleConfigType_STATUSMESSAGE_CONFIG+1))
#define _meshtastic_AdminMessage_BackupLocation_MIN meshtastic_AdminMessage_BackupLocation_FLASH
#define _meshtastic_AdminMessage_BackupLocation_MAX meshtastic_AdminMessage_BackupLocation_SD

View File

@@ -361,7 +361,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 2279
#define meshtastic_BackupPreferences_size 2362
#define meshtastic_ChannelFile_size 718
#define meshtastic_DeviceState_size 1737
#define meshtastic_NodeInfoLite_size 196

View File

@@ -87,6 +87,9 @@ typedef struct _meshtastic_LocalModuleConfig {
/* Paxcounter Config */
bool has_paxcounter;
meshtastic_ModuleConfig_PaxcounterConfig paxcounter;
/* StatusMessage Config */
bool has_statusmessage;
meshtastic_ModuleConfig_StatusMessageConfig statusmessage;
} meshtastic_LocalModuleConfig;
@@ -96,9 +99,9 @@ extern "C" {
/* Initializer values for message structs */
#define meshtastic_LocalConfig_init_default {false, meshtastic_Config_DeviceConfig_init_default, false, meshtastic_Config_PositionConfig_init_default, false, meshtastic_Config_PowerConfig_init_default, false, meshtastic_Config_NetworkConfig_init_default, false, meshtastic_Config_DisplayConfig_init_default, false, meshtastic_Config_LoRaConfig_init_default, false, meshtastic_Config_BluetoothConfig_init_default, 0, false, meshtastic_Config_SecurityConfig_init_default}
#define meshtastic_LocalModuleConfig_init_default {false, meshtastic_ModuleConfig_MQTTConfig_init_default, false, meshtastic_ModuleConfig_SerialConfig_init_default, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_default, false, meshtastic_ModuleConfig_StoreForwardConfig_init_default, false, meshtastic_ModuleConfig_RangeTestConfig_init_default, false, meshtastic_ModuleConfig_TelemetryConfig_init_default, false, meshtastic_ModuleConfig_CannedMessageConfig_init_default, 0, false, meshtastic_ModuleConfig_AudioConfig_init_default, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_default, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_default, false, meshtastic_ModuleConfig_AmbientLightingConfig_init_default, false, meshtastic_ModuleConfig_DetectionSensorConfig_init_default, false, meshtastic_ModuleConfig_PaxcounterConfig_init_default}
#define meshtastic_LocalModuleConfig_init_default {false, meshtastic_ModuleConfig_MQTTConfig_init_default, false, meshtastic_ModuleConfig_SerialConfig_init_default, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_default, false, meshtastic_ModuleConfig_StoreForwardConfig_init_default, false, meshtastic_ModuleConfig_RangeTestConfig_init_default, false, meshtastic_ModuleConfig_TelemetryConfig_init_default, false, meshtastic_ModuleConfig_CannedMessageConfig_init_default, 0, false, meshtastic_ModuleConfig_AudioConfig_init_default, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_default, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_default, false, meshtastic_ModuleConfig_AmbientLightingConfig_init_default, false, meshtastic_ModuleConfig_DetectionSensorConfig_init_default, false, meshtastic_ModuleConfig_PaxcounterConfig_init_default, false, meshtastic_ModuleConfig_StatusMessageConfig_init_default}
#define meshtastic_LocalConfig_init_zero {false, meshtastic_Config_DeviceConfig_init_zero, false, meshtastic_Config_PositionConfig_init_zero, false, meshtastic_Config_PowerConfig_init_zero, false, meshtastic_Config_NetworkConfig_init_zero, false, meshtastic_Config_DisplayConfig_init_zero, false, meshtastic_Config_LoRaConfig_init_zero, false, meshtastic_Config_BluetoothConfig_init_zero, 0, false, meshtastic_Config_SecurityConfig_init_zero}
#define meshtastic_LocalModuleConfig_init_zero {false, meshtastic_ModuleConfig_MQTTConfig_init_zero, false, meshtastic_ModuleConfig_SerialConfig_init_zero, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero, false, meshtastic_ModuleConfig_StoreForwardConfig_init_zero, false, meshtastic_ModuleConfig_RangeTestConfig_init_zero, false, meshtastic_ModuleConfig_TelemetryConfig_init_zero, false, meshtastic_ModuleConfig_CannedMessageConfig_init_zero, 0, false, meshtastic_ModuleConfig_AudioConfig_init_zero, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_zero, false, meshtastic_ModuleConfig_AmbientLightingConfig_init_zero, false, meshtastic_ModuleConfig_DetectionSensorConfig_init_zero, false, meshtastic_ModuleConfig_PaxcounterConfig_init_zero}
#define meshtastic_LocalModuleConfig_init_zero {false, meshtastic_ModuleConfig_MQTTConfig_init_zero, false, meshtastic_ModuleConfig_SerialConfig_init_zero, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero, false, meshtastic_ModuleConfig_StoreForwardConfig_init_zero, false, meshtastic_ModuleConfig_RangeTestConfig_init_zero, false, meshtastic_ModuleConfig_TelemetryConfig_init_zero, false, meshtastic_ModuleConfig_CannedMessageConfig_init_zero, 0, false, meshtastic_ModuleConfig_AudioConfig_init_zero, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_zero, false, meshtastic_ModuleConfig_AmbientLightingConfig_init_zero, false, meshtastic_ModuleConfig_DetectionSensorConfig_init_zero, false, meshtastic_ModuleConfig_PaxcounterConfig_init_zero, false, meshtastic_ModuleConfig_StatusMessageConfig_init_zero}
/* Field tags (for use in manual encoding/decoding) */
#define meshtastic_LocalConfig_device_tag 1
@@ -124,6 +127,7 @@ extern "C" {
#define meshtastic_LocalModuleConfig_ambient_lighting_tag 12
#define meshtastic_LocalModuleConfig_detection_sensor_tag 13
#define meshtastic_LocalModuleConfig_paxcounter_tag 14
#define meshtastic_LocalModuleConfig_statusmessage_tag 15
/* Struct field encoding specification for nanopb */
#define meshtastic_LocalConfig_FIELDLIST(X, a) \
@@ -161,7 +165,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, remote_hardware, 10) \
X(a, STATIC, OPTIONAL, MESSAGE, neighbor_info, 11) \
X(a, STATIC, OPTIONAL, MESSAGE, ambient_lighting, 12) \
X(a, STATIC, OPTIONAL, MESSAGE, detection_sensor, 13) \
X(a, STATIC, OPTIONAL, MESSAGE, paxcounter, 14)
X(a, STATIC, OPTIONAL, MESSAGE, paxcounter, 14) \
X(a, STATIC, OPTIONAL, MESSAGE, statusmessage, 15)
#define meshtastic_LocalModuleConfig_CALLBACK NULL
#define meshtastic_LocalModuleConfig_DEFAULT NULL
#define meshtastic_LocalModuleConfig_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig
@@ -177,6 +182,7 @@ X(a, STATIC, OPTIONAL, MESSAGE, paxcounter, 14)
#define meshtastic_LocalModuleConfig_ambient_lighting_MSGTYPE meshtastic_ModuleConfig_AmbientLightingConfig
#define meshtastic_LocalModuleConfig_detection_sensor_MSGTYPE meshtastic_ModuleConfig_DetectionSensorConfig
#define meshtastic_LocalModuleConfig_paxcounter_MSGTYPE meshtastic_ModuleConfig_PaxcounterConfig
#define meshtastic_LocalModuleConfig_statusmessage_MSGTYPE meshtastic_ModuleConfig_StatusMessageConfig
extern const pb_msgdesc_t meshtastic_LocalConfig_msg;
extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
@@ -186,9 +192,9 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
#define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg
/* Maximum encoded size of messages (where known) */
#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalConfig_size
#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalModuleConfig_size
#define meshtastic_LocalConfig_size 749
#define meshtastic_LocalModuleConfig_size 675
#define meshtastic_LocalModuleConfig_size 758
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -30,6 +30,9 @@ PB_BIND(meshtastic_StoreForwardPlusPlus, meshtastic_StoreForwardPlusPlus, 2)
PB_BIND(meshtastic_Waypoint, meshtastic_Waypoint, AUTO)
PB_BIND(meshtastic_StatusMessage, meshtastic_StatusMessage, AUTO)
PB_BIND(meshtastic_MqttClientProxyMessage, meshtastic_MqttClientProxyMessage, 2)

View File

@@ -858,6 +858,11 @@ typedef struct _meshtastic_Waypoint {
uint32_t icon;
} meshtastic_Waypoint;
/* Message for node status */
typedef struct _meshtastic_StatusMessage {
char status[80];
} meshtastic_StatusMessage;
typedef PB_BYTES_ARRAY_T(435) meshtastic_MqttClientProxyMessage_data_t;
/* This message will be proxied over the PhoneAPI for the client to deliver to the MQTT server */
typedef struct _meshtastic_MqttClientProxyMessage {
@@ -1402,6 +1407,7 @@ extern "C" {
#define meshtastic_MeshPacket_priority_ENUMTYPE meshtastic_MeshPacket_Priority
#define meshtastic_MeshPacket_delayed_ENUMTYPE meshtastic_MeshPacket_Delayed
#define meshtastic_MeshPacket_transport_mechanism_ENUMTYPE meshtastic_MeshPacket_TransportMechanism
@@ -1444,6 +1450,7 @@ extern "C" {
#define meshtastic_KeyVerification_init_default {0, {0, {0}}, {0, {0}}}
#define meshtastic_StoreForwardPlusPlus_init_default {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0, 0}
#define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0}
#define meshtastic_StatusMessage_init_default {""}
#define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0}
#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN}
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0, 0, 0}
@@ -1476,6 +1483,7 @@ extern "C" {
#define meshtastic_KeyVerification_init_zero {0, {0, {0}}, {0, {0}}}
#define meshtastic_StoreForwardPlusPlus_init_zero {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0, 0}
#define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0}
#define meshtastic_StatusMessage_init_zero {""}
#define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0}
#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN}
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0, 0, 0}
@@ -1571,6 +1579,7 @@ extern "C" {
#define meshtastic_Waypoint_name_tag 6
#define meshtastic_Waypoint_description_tag 7
#define meshtastic_Waypoint_icon_tag 8
#define meshtastic_StatusMessage_status_tag 1
#define meshtastic_MqttClientProxyMessage_topic_tag 1
#define meshtastic_MqttClientProxyMessage_data_tag 2
#define meshtastic_MqttClientProxyMessage_text_tag 3
@@ -1806,6 +1815,11 @@ X(a, STATIC, SINGULAR, FIXED32, icon, 8)
#define meshtastic_Waypoint_CALLBACK NULL
#define meshtastic_Waypoint_DEFAULT NULL
#define meshtastic_StatusMessage_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, STRING, status, 1)
#define meshtastic_StatusMessage_CALLBACK NULL
#define meshtastic_StatusMessage_DEFAULT NULL
#define meshtastic_MqttClientProxyMessage_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, STRING, topic, 1) \
X(a, STATIC, ONEOF, BYTES, (payload_variant,data,payload_variant.data), 2) \
@@ -2072,6 +2086,7 @@ extern const pb_msgdesc_t meshtastic_Data_msg;
extern const pb_msgdesc_t meshtastic_KeyVerification_msg;
extern const pb_msgdesc_t meshtastic_StoreForwardPlusPlus_msg;
extern const pb_msgdesc_t meshtastic_Waypoint_msg;
extern const pb_msgdesc_t meshtastic_StatusMessage_msg;
extern const pb_msgdesc_t meshtastic_MqttClientProxyMessage_msg;
extern const pb_msgdesc_t meshtastic_MeshPacket_msg;
extern const pb_msgdesc_t meshtastic_NodeInfo_msg;
@@ -2106,6 +2121,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
#define meshtastic_KeyVerification_fields &meshtastic_KeyVerification_msg
#define meshtastic_StoreForwardPlusPlus_fields &meshtastic_StoreForwardPlusPlus_msg
#define meshtastic_Waypoint_fields &meshtastic_Waypoint_msg
#define meshtastic_StatusMessage_fields &meshtastic_StatusMessage_msg
#define meshtastic_MqttClientProxyMessage_fields &meshtastic_MqttClientProxyMessage_msg
#define meshtastic_MeshPacket_fields &meshtastic_MeshPacket_msg
#define meshtastic_NodeInfo_fields &meshtastic_NodeInfo_msg
@@ -2161,6 +2177,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
#define meshtastic_QueueStatus_size 23
#define meshtastic_RouteDiscovery_size 256
#define meshtastic_Routing_size 259
#define meshtastic_StatusMessage_size 81
#define meshtastic_StoreForwardPlusPlus_size 377
#define meshtastic_ToRadio_size 504
#define meshtastic_User_size 115

View File

@@ -51,6 +51,9 @@ PB_BIND(meshtastic_ModuleConfig_CannedMessageConfig, meshtastic_ModuleConfig_Can
PB_BIND(meshtastic_ModuleConfig_AmbientLightingConfig, meshtastic_ModuleConfig_AmbientLightingConfig, AUTO)
PB_BIND(meshtastic_ModuleConfig_StatusMessageConfig, meshtastic_ModuleConfig_StatusMessageConfig, AUTO)
PB_BIND(meshtastic_RemoteHardwarePin, meshtastic_RemoteHardwarePin, AUTO)

View File

@@ -409,6 +409,12 @@ typedef struct _meshtastic_ModuleConfig_AmbientLightingConfig {
uint8_t blue;
} meshtastic_ModuleConfig_AmbientLightingConfig;
/* StatusMessage config - Allows setting a status message for a node to periodically rebroadcast */
typedef struct _meshtastic_ModuleConfig_StatusMessageConfig {
/* The actual status string */
char node_status[80];
} meshtastic_ModuleConfig_StatusMessageConfig;
/* A GPIO pin definition for remote hardware module */
typedef struct _meshtastic_RemoteHardwarePin {
/* GPIO Pin number (must match Arduino) */
@@ -460,6 +466,8 @@ typedef struct _meshtastic_ModuleConfig {
meshtastic_ModuleConfig_DetectionSensorConfig detection_sensor;
/* TODO: REPLACE */
meshtastic_ModuleConfig_PaxcounterConfig paxcounter;
/* TODO: REPLACE */
meshtastic_ModuleConfig_StatusMessageConfig statusmessage;
} payload_variant;
} meshtastic_ModuleConfig;
@@ -515,6 +523,7 @@ extern "C" {
#define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_event_press_ENUMTYPE meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar
#define meshtastic_RemoteHardwarePin_type_ENUMTYPE meshtastic_RemoteHardwarePinType
@@ -534,6 +543,7 @@ extern "C" {
#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
#define meshtastic_ModuleConfig_AmbientLightingConfig_init_default {0, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_StatusMessageConfig_init_default {""}
#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}
@@ -550,6 +560,7 @@ extern "C" {
#define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
#define meshtastic_ModuleConfig_AmbientLightingConfig_init_zero {0, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_StatusMessageConfig_init_zero {""}
#define meshtastic_RemoteHardwarePin_init_zero {0, "", _meshtastic_RemoteHardwarePinType_MIN}
/* Field tags (for use in manual encoding/decoding) */
@@ -653,6 +664,7 @@ extern "C" {
#define meshtastic_ModuleConfig_AmbientLightingConfig_red_tag 3
#define meshtastic_ModuleConfig_AmbientLightingConfig_green_tag 4
#define meshtastic_ModuleConfig_AmbientLightingConfig_blue_tag 5
#define meshtastic_ModuleConfig_StatusMessageConfig_node_status_tag 1
#define meshtastic_RemoteHardwarePin_gpio_pin_tag 1
#define meshtastic_RemoteHardwarePin_name_tag 2
#define meshtastic_RemoteHardwarePin_type_tag 3
@@ -672,6 +684,7 @@ extern "C" {
#define meshtastic_ModuleConfig_ambient_lighting_tag 11
#define meshtastic_ModuleConfig_detection_sensor_tag 12
#define meshtastic_ModuleConfig_paxcounter_tag 13
#define meshtastic_ModuleConfig_statusmessage_tag 14
/* Struct field encoding specification for nanopb */
#define meshtastic_ModuleConfig_FIELDLIST(X, a) \
@@ -687,7 +700,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,remote_hardware,payload_vari
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,neighbor_info,payload_variant.neighbor_info), 10) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,ambient_lighting,payload_variant.ambient_lighting), 11) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,detection_sensor,payload_variant.detection_sensor), 12) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,paxcounter,payload_variant.paxcounter), 13)
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,paxcounter,payload_variant.paxcounter), 13) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,statusmessage,payload_variant.statusmessage), 14)
#define meshtastic_ModuleConfig_CALLBACK NULL
#define meshtastic_ModuleConfig_DEFAULT NULL
#define meshtastic_ModuleConfig_payload_variant_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig
@@ -703,6 +717,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,paxcounter,payload_variant.p
#define meshtastic_ModuleConfig_payload_variant_ambient_lighting_MSGTYPE meshtastic_ModuleConfig_AmbientLightingConfig
#define meshtastic_ModuleConfig_payload_variant_detection_sensor_MSGTYPE meshtastic_ModuleConfig_DetectionSensorConfig
#define meshtastic_ModuleConfig_payload_variant_paxcounter_MSGTYPE meshtastic_ModuleConfig_PaxcounterConfig
#define meshtastic_ModuleConfig_payload_variant_statusmessage_MSGTYPE meshtastic_ModuleConfig_StatusMessageConfig
#define meshtastic_ModuleConfig_MQTTConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
@@ -865,6 +880,11 @@ X(a, STATIC, SINGULAR, UINT32, blue, 5)
#define meshtastic_ModuleConfig_AmbientLightingConfig_CALLBACK NULL
#define meshtastic_ModuleConfig_AmbientLightingConfig_DEFAULT NULL
#define meshtastic_ModuleConfig_StatusMessageConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, STRING, node_status, 1)
#define meshtastic_ModuleConfig_StatusMessageConfig_CALLBACK NULL
#define meshtastic_ModuleConfig_StatusMessageConfig_DEFAULT NULL
#define meshtastic_RemoteHardwarePin_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, gpio_pin, 1) \
X(a, STATIC, SINGULAR, STRING, name, 2) \
@@ -887,6 +907,7 @@ extern const pb_msgdesc_t meshtastic_ModuleConfig_RangeTestConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_TelemetryConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_CannedMessageConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_AmbientLightingConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_StatusMessageConfig_msg;
extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
@@ -905,6 +926,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
#define meshtastic_ModuleConfig_TelemetryConfig_fields &meshtastic_ModuleConfig_TelemetryConfig_msg
#define meshtastic_ModuleConfig_CannedMessageConfig_fields &meshtastic_ModuleConfig_CannedMessageConfig_msg
#define meshtastic_ModuleConfig_AmbientLightingConfig_fields &meshtastic_ModuleConfig_AmbientLightingConfig_msg
#define meshtastic_ModuleConfig_StatusMessageConfig_fields &meshtastic_ModuleConfig_StatusMessageConfig_msg
#define meshtastic_RemoteHardwarePin_fields &meshtastic_RemoteHardwarePin_msg
/* Maximum encoded size of messages (where known) */
@@ -921,6 +943,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
#define meshtastic_ModuleConfig_RangeTestConfig_size 12
#define meshtastic_ModuleConfig_RemoteHardwareConfig_size 96
#define meshtastic_ModuleConfig_SerialConfig_size 28
#define meshtastic_ModuleConfig_StatusMessageConfig_size 81
#define meshtastic_ModuleConfig_StoreForwardConfig_size 24
#define meshtastic_ModuleConfig_TelemetryConfig_size 50
#define meshtastic_ModuleConfig_size 227

View File

@@ -91,6 +91,11 @@ typedef enum _meshtastic_PortNum {
This module is specifically for Native Linux nodes, and provides a Git-style
chain of messages. */
meshtastic_PortNum_STORE_FORWARD_PLUSPLUS_APP = 35,
/* Node Status module
ENCODING: protobuf
This module allows setting an extra string of status for a node.
Broadcasts on change and on a timer, possibly once a day. */
meshtastic_PortNum_NODE_STATUS_APP = 36,
/* Provides a hardware serial interface to send and receive from the Meshtastic network.
Connect to the RX/TX pins of a device with 38400 8N1. Packets received from the Meshtastic
network is forwarded to the RX pin while sending a packet to TX will go out to the Mesh network.

View File

@@ -361,6 +361,8 @@ typedef struct _meshtastic_LocalStats {
uint32_t heap_free_bytes;
/* Number of packets that were dropped because the transmit queue was full. */
uint16_t num_tx_dropped;
/* Noise floor value measured in dBm */
int32_t noise_floor;
} meshtastic_LocalStats;
/* Health telemetry metrics */
@@ -458,7 +460,7 @@ extern "C" {
#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}
#define meshtastic_PowerMetrics_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}
#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, 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, 0, 0, 0}
#define meshtastic_LocalStats_init_default {0, 0, 0, 0, 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, false, ""}
#define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}}
@@ -467,7 +469,7 @@ extern "C" {
#define meshtastic_EnvironmentMetrics_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, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
#define meshtastic_PowerMetrics_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, false, 0, false, 0, false, 0}
#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, 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, 0, 0, 0}
#define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 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, false, ""}
#define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}}
@@ -556,6 +558,7 @@ extern "C" {
#define meshtastic_LocalStats_heap_total_bytes_tag 12
#define meshtastic_LocalStats_heap_free_bytes_tag 13
#define meshtastic_LocalStats_num_tx_dropped_tag 14
#define meshtastic_LocalStats_noise_floor_tag 15
#define meshtastic_HealthMetrics_heart_bpm_tag 1
#define meshtastic_HealthMetrics_spO2_tag 2
#define meshtastic_HealthMetrics_temperature_tag 3
@@ -678,7 +681,8 @@ X(a, STATIC, SINGULAR, UINT32, num_tx_relay, 10) \
X(a, STATIC, SINGULAR, UINT32, num_tx_relay_canceled, 11) \
X(a, STATIC, SINGULAR, UINT32, heap_total_bytes, 12) \
X(a, STATIC, SINGULAR, UINT32, heap_free_bytes, 13) \
X(a, STATIC, SINGULAR, UINT32, num_tx_dropped, 14)
X(a, STATIC, SINGULAR, UINT32, num_tx_dropped, 14) \
X(a, STATIC, SINGULAR, INT32, noise_floor, 15)
#define meshtastic_LocalStats_CALLBACK NULL
#define meshtastic_LocalStats_DEFAULT NULL
@@ -755,7 +759,7 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg;
#define meshtastic_EnvironmentMetrics_size 113
#define meshtastic_HealthMetrics_size 11
#define meshtastic_HostMetrics_size 264
#define meshtastic_LocalStats_size 76
#define meshtastic_LocalStats_size 87
#define meshtastic_Nau7802Config_size 16
#define meshtastic_PowerMetrics_size 81
#define meshtastic_Telemetry_size 272

View File

@@ -235,22 +235,46 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
}
case meshtastic_AdminMessage_ota_request_tag: {
#if defined(ARCH_ESP32)
LOG_INFO("OTA Requested");
if (r->ota_request.ota_hash.size != 32) {
suppressRebootBanner = true;
LOG_INFO("OTA Failed: Invalid `ota_hash` provided");
sendWarningAndLog("Cannot start OTA: Invalid `ota_hash` provided.");
break;
}
meshtastic_OTAMode mode = r->ota_request.reboot_ota_mode;
const char *mode_name = (mode == METHOD_OTA_BLE ? "BLE" : "WiFi");
// Check that we have an OTA partition
const esp_partition_t *part = MeshtasticOTA::getAppPartition();
if (part == NULL) {
suppressRebootBanner = true;
sendWarningAndLog("Cannot start OTA: Cannot find OTA Loader partition.");
break;
}
static esp_app_desc_t app_desc;
if (!MeshtasticOTA::getAppDesc(part, &app_desc)) {
suppressRebootBanner = true;
sendWarningAndLog("Cannot start OTA: Device does have a valid OTA Loader.");
break;
}
if (!MeshtasticOTA::checkOTACapability(&app_desc, mode)) {
suppressRebootBanner = true;
sendWarningAndLog("OTA Loader does not support %s", mode_name);
break;
}
if (MeshtasticOTA::trySwitchToOTA()) {
LOG_INFO("OTA Requested");
suppressRebootBanner = true;
if (screen)
screen->startFirmwareUpdateScreen();
MeshtasticOTA::saveConfig(&config.network, mode, r->ota_request.ota_hash.bytes);
LOG_INFO("Rebooting to WiFi OTA");
sendWarningAndLog("Rebooting to %s OTA", mode_name);
} else {
LOG_INFO("WIFI OTA Failed");
sendWarningAndLog("Unable to switch to the OTA partition.");
}
#endif
int s = 1; // Reboot in 1 second, hard coded
@@ -881,10 +905,11 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
bool AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
{
bool shouldReboot = true;
// If we are in an open transaction or configuring MQTT or Serial (which have validation), defer disabling Bluetooth
// Otherwise, disable Bluetooth to prevent the phone from interfering with the config
if (!hasOpenEditTransaction &&
!IS_ONE_OF(c.which_payload_variant, meshtastic_ModuleConfig_mqtt_tag, meshtastic_ModuleConfig_serial_tag)) {
if (!hasOpenEditTransaction && !IS_ONE_OF(c.which_payload_variant, meshtastic_ModuleConfig_mqtt_tag,
meshtastic_ModuleConfig_serial_tag, meshtastic_ModuleConfig_statusmessage_tag)) {
disableBluetooth();
}
@@ -976,8 +1001,14 @@ bool AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
moduleConfig.has_paxcounter = true;
moduleConfig.paxcounter = c.payload_variant.paxcounter;
break;
case meshtastic_ModuleConfig_statusmessage_tag:
LOG_INFO("Set module config: StatusMessage");
moduleConfig.has_statusmessage = true;
moduleConfig.statusmessage = c.payload_variant.statusmessage;
shouldReboot = false;
break;
}
saveChanges(SEGMENT_MODULECONFIG);
saveChanges(SEGMENT_MODULECONFIG, shouldReboot);
return true;
}
@@ -1156,6 +1187,11 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_paxcounter_tag;
res.get_module_config_response.payload_variant.paxcounter = moduleConfig.paxcounter;
break;
case meshtastic_AdminMessage_ModuleConfigType_STATUSMESSAGE_CONFIG:
LOG_INFO("Get module config: StatusMessage");
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_statusmessage_tag;
res.get_module_config_response.payload_variant.statusmessage = moduleConfig.statusmessage;
break;
}
// NOTE: The phone app needs to know the ls_secsvalue so it can properly expect sleep behavior.
@@ -1472,15 +1508,43 @@ void AdminModule::handleSendInputEvent(const meshtastic_AdminMessage_InputEvent
#endif
}
void AdminModule::sendWarning(const char *message)
void AdminModule::sendWarning(const char *format, ...)
{
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
if (!cn)
return;
cn->level = meshtastic_LogRecord_Level_WARNING;
cn->time = getValidTime(RTCQualityFromNet);
strncpy(cn->message, message, sizeof(cn->message));
va_list args;
va_start(args, format);
// Format the arguments directly into the notification object
vsnprintf(cn->message, sizeof(cn->message), format, args);
va_end(args);
service->sendClientNotification(cn);
}
void AdminModule::sendWarningAndLog(const char *format, ...)
{
// We need a temporary buffer to hold the formatted text so we can log it
// Using 250 bytes as a safe upper limit for typical text notifications
char buf[250];
va_list args;
va_start(args, format);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
LOG_WARN(buf);
// 2. Call sendWarning
// SECURITY NOTE: We pass "%s", buf instead of just 'buf'.
// If 'buf' contained a % symbol (e.g. "Battery 50%"), passing it directly
// would crash sendWarning. "%s" treats it purely as text.
sendWarning("%s", buf);
}
void disableBluetooth()
{
#if HAS_BLUETOOTH

View File

@@ -1,7 +1,9 @@
#include <sys/types.h>
#pragma once
#ifdef ESP_PLATFORM
#include <esp_ota_ops.h>
#endif
#include "ProtobufModule.h"
#include <sys/types.h>
#if HAS_WIFI
#include "mesh/wifi/WiFiAPClient.h"
#endif
@@ -71,7 +73,8 @@ class AdminModule : public ProtobufModule<meshtastic_AdminMessage>, public Obser
bool messageIsResponse(const meshtastic_AdminMessage *r);
bool messageIsRequest(const meshtastic_AdminMessage *r);
void sendWarning(const char *message);
void sendWarning(const char *format, ...) __attribute__((format(printf, 2, 3)));
void sendWarningAndLog(const char *format, ...) __attribute__((format(printf, 2, 3)));
};
static constexpr const char *licensedModeMessage =

View File

@@ -108,6 +108,9 @@
#if !MESHTASTIC_EXCLUDE_DROPZONE
#include "modules/DropzoneModule.h"
#endif
#if !MESHTASTIC_EXCLUDE_STATUS
#include "modules/StatusMessageModule.h"
#endif
/**
* Create module instances here. If you are adding a new module, you must 'new' it here (or somewhere else)
@@ -165,6 +168,9 @@ void setupModules()
#if !MESHTASTIC_EXCLUDE_DROPZONE
dropzoneModule = new DropzoneModule();
#endif
#if !MESHTASTIC_EXCLUDE_STATUS
statusMessageModule = new StatusMessageModule();
#endif
#if !MESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE
new GenericThreadModule();
#endif

View File

@@ -50,9 +50,10 @@ int StatusLEDModule::handleStatusUpdate(const meshtastic::Status *arg)
break;
}
case meshtastic::BluetoothStatus::ConnectionState::CONNECTED: {
ble_state = connected;
PAIRING_LED_starttime = millis();
break;
if (ble_state != connected) {
ble_state = connected;
PAIRING_LED_starttime = millis();
}
}
}

View File

@@ -0,0 +1,41 @@
#if !MESHTASTIC_EXCLUDE_STATUS
#include "StatusMessageModule.h"
#include "MeshService.h"
#include "ProtobufModule.h"
StatusMessageModule *statusMessageModule;
int32_t StatusMessageModule::runOnce()
{
if (moduleConfig.has_statusmessage && moduleConfig.statusmessage.node_status[0] != '\0') {
// create and send message with the status message set
meshtastic_StatusMessage ourStatus = meshtastic_StatusMessage_init_zero;
strncpy(ourStatus.status, moduleConfig.statusmessage.node_status, sizeof(ourStatus.status));
ourStatus.status[sizeof(ourStatus.status) - 1] = '\0'; // ensure null termination
meshtastic_MeshPacket *p = allocDataPacket();
p->decoded.payload.size = pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes),
meshtastic_StatusMessage_fields, &ourStatus);
p->to = NODENUM_BROADCAST;
p->decoded.want_response = false;
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
p->channel = 0;
service->sendToMesh(p);
}
return 1000 * 12 * 60 * 60;
}
ProcessMessage StatusMessageModule::handleReceived(const meshtastic_MeshPacket &mp)
{
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
meshtastic_StatusMessage incomingMessage;
if (pb_decode_from_bytes(mp.decoded.payload.bytes, mp.decoded.payload.size, meshtastic_StatusMessage_fields,
&incomingMessage)) {
LOG_INFO("Received a NodeStatus message %s", incomingMessage.status);
}
}
return ProcessMessage::CONTINUE;
}
#endif

View File

@@ -0,0 +1,35 @@
#pragma once
#if !MESHTASTIC_EXCLUDE_STATUS
#include "SinglePortModule.h"
#include "configuration.h"
class StatusMessageModule : public SinglePortModule, private concurrency::OSThread
{
public:
/** Constructor
* name is for debugging output
*/
StatusMessageModule()
: SinglePortModule("statusMessage", meshtastic_PortNum_NODE_STATUS_APP), concurrency::OSThread("StatusMessage")
{
if (moduleConfig.has_statusmessage && moduleConfig.statusmessage.node_status[0] != '\0') {
this->setInterval(2 * 60 * 1000);
} else {
this->setInterval(1000 * 12 * 60 * 60);
}
// TODO: If we have a string, set the initial delay (15 minutes maybe)
}
virtual int32_t runOnce() override;
protected:
/** Called to handle a particular incoming message
*/
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) override;
private:
};
extern StatusMessageModule *statusMessageModule;
#endif

View File

@@ -1,13 +1,17 @@
#include "MeshtasticOTA.h"
#include "configuration.h"
#ifdef ESP_PLATFORM
#include <Preferences.h>
#include <esp_ota_ops.h>
#endif
namespace MeshtasticOTA
{
static const char *nvsNamespace = "MeshtasticOTA";
static const char *appProjectName = "MeshtasticOTA";
static const char *combinedAppProjectName = "MeshtasticOTA";
static const char *bleOnlyAppProjectName = "MeshtasticOTA-BLE";
static const char *wifiOnlyAppProjectName = "MeshtasticOTA-WiFi";
static bool updated = false;
@@ -68,21 +72,44 @@ bool getAppDesc(const esp_partition_t *part, esp_app_desc_t *app_desc)
LOG_INFO("esp_ota_get_partition_description failed");
return false;
}
if (strcmp(app_desc->project_name, appProjectName) != 0) {
LOG_INFO("app_desc->project_name == 0");
return false;
}
return true;
}
bool checkOTACapability(esp_app_desc_t *app_desc, uint8_t method)
{
// Combined loader supports all (both) transports, BLE and WiFi
if (strcmp(app_desc->project_name, combinedAppProjectName) == 0) {
LOG_INFO("OTA partition contains combined BLE/WiFi OTA Loader");
return true;
}
if (method == METHOD_OTA_BLE && strcmp(app_desc->project_name, bleOnlyAppProjectName) == 0) {
LOG_INFO("OTA partition contains BLE-only OTA Loader");
return true;
}
if (method == METHOD_OTA_WIFI && strcmp(app_desc->project_name, wifiOnlyAppProjectName) == 0) {
LOG_INFO("OTA partition contains WiFi-only OTA Loader");
return true;
}
LOG_INFO("OTA partition does not contain a known OTA loader");
return false;
}
bool trySwitchToOTA()
{
const esp_partition_t *part = getAppPartition();
esp_app_desc_t app_desc;
if (!getAppDesc(part, &app_desc))
if (part == NULL) {
LOG_WARN("Unable to get app partition in preparation of OTA reboot");
return false;
if (esp_ota_set_boot_partition(part) != ESP_OK)
}
uint8_t result = esp_ota_set_boot_partition(part);
// Partition and app checks should now be done in the AdminModule before this is called
if (result != ESP_OK) {
LOG_WARN("Unable to switch to OTA partiton. (Reason %d)", result);
return false;
}
return true;
}

View File

@@ -3,12 +3,20 @@
#include "mesh-pb-constants.h"
#include <Arduino.h>
#ifdef ESP_PLATFORM
#include <esp_ota_ops.h>
#endif
#define METHOD_OTA_BLE 1
#define METHOD_OTA_WIFI 2
namespace MeshtasticOTA
{
void initialize();
bool isUpdated();
const esp_partition_t *getAppPartition();
bool getAppDesc(const esp_partition_t *part, esp_app_desc_t *app_desc);
bool checkOTACapability(esp_app_desc_t *app_desc, uint8_t method);
void recoverConfig(meshtastic_Config_NetworkConfig *network);
void saveConfig(meshtastic_Config_NetworkConfig *network, meshtastic_OTAMode method, uint8_t *ota_hash);
bool trySwitchToOTA();

View File

@@ -65,7 +65,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
return ARGP_ERR_UNKNOWN;
else
checkConfigPort = false;
printf("Using config file %d\n", TCPPort);
printf("Using config file %d\n", TCPPort);
break;
case 'c':
configPath = arg;
@@ -847,6 +847,7 @@ bool loadConfig(const char *configPath)
}
if (yamlConfig["Config"]) {
portduino_config.has_config_overrides = true;
if (yamlConfig["Config"]["DisplayMode"]) {
portduino_config.has_configDisplayMode = true;
if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "TWOCOLOR") {
@@ -859,6 +860,13 @@ bool loadConfig(const char *configPath)
portduino_config.configDisplayMode = meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT;
}
}
if (yamlConfig["Config"]["StatusMessage"]) {
portduino_config.has_statusMessage = true;
portduino_config.statusMessage = (yamlConfig["Config"]["StatusMessage"]).as<std::string>("");
}
if ((yamlConfig["Config"]["EnableUDP"]).as<bool>(false)) {
portduino_config.enable_UDP = true;
}
}
if (yamlConfig["General"]) {
@@ -874,10 +882,8 @@ bool loadConfig(const char *configPath)
}
if (checkConfigPort) {
portduino_config.api_port = (yamlConfig["General"]["APIPort"]).as<int>(-1);
if (portduino_config.api_port != -1 &&
portduino_config.api_port > 1023 &&
portduino_config.api_port < 65536) {
TCPPort = (portduino_config.api_port);
if (portduino_config.api_port != -1 && portduino_config.api_port > 1023 && portduino_config.api_port < 65536) {
TCPPort = (portduino_config.api_port);
}
}
portduino_config.mac_address = (yamlConfig["General"]["MACAddress"]).as<std::string>("");

View File

@@ -168,8 +168,12 @@ extern struct portduino_config_struct {
int hostMetrics_channel = 0;
// config
bool has_config_overrides = false;
int configDisplayMode = 0;
bool has_configDisplayMode = false;
std::string statusMessage = "";
bool has_statusMessage = false;
bool enable_UDP = false;
// General
std::string mac_address = "";
@@ -485,21 +489,30 @@ extern struct portduino_config_struct {
}
// config
if (has_configDisplayMode) {
if (has_config_overrides) {
out << YAML::Key << "Config" << YAML::Value << YAML::BeginMap;
switch (configDisplayMode) {
case meshtastic_Config_DisplayConfig_DisplayMode_TWOCOLOR:
out << YAML::Key << "DisplayMode" << YAML::Value << "TWOCOLOR";
break;
case meshtastic_Config_DisplayConfig_DisplayMode_INVERTED:
out << YAML::Key << "DisplayMode" << YAML::Value << "INVERTED";
break;
case meshtastic_Config_DisplayConfig_DisplayMode_COLOR:
out << YAML::Key << "DisplayMode" << YAML::Value << "COLOR";
break;
case meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT:
out << YAML::Key << "DisplayMode" << YAML::Value << "DEFAULT";
break;
if (has_configDisplayMode) {
switch (configDisplayMode) {
case meshtastic_Config_DisplayConfig_DisplayMode_TWOCOLOR:
out << YAML::Key << "DisplayMode" << YAML::Value << "TWOCOLOR";
break;
case meshtastic_Config_DisplayConfig_DisplayMode_INVERTED:
out << YAML::Key << "DisplayMode" << YAML::Value << "INVERTED";
break;
case meshtastic_Config_DisplayConfig_DisplayMode_COLOR:
out << YAML::Key << "DisplayMode" << YAML::Value << "COLOR";
break;
case meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT:
out << YAML::Key << "DisplayMode" << YAML::Value << "DEFAULT";
break;
}
}
if (has_statusMessage) {
out << YAML::Key << "StatusMessage" << YAML::Value << statusMessage;
}
if (enable_UDP) {
out << YAML::Key << "EnableUDP" << YAML::Value << true;
}
out << YAML::EndMap; // Config

View File

@@ -7,3 +7,22 @@ custom_esp32_kind = esp32
build_flags =
${esp32_common.build_flags}
-DMESHTASTIC_EXCLUDE_AUDIO=1
; Override lib_deps to use environmental_extra_no_bsec instead of environmental_extra
; BSEC library uses ~3.5KB DRAM which causes overflow on original ESP32 targets
lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${networking_extra.lib_deps}
${environmental_base.lib_deps}
${environmental_extra_no_bsec.lib_deps}
${radiolib_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-esp32_https_server packageName=https://github.com/meshtastic/esp32_https_server gitBranch=master
https://github.com/meshtastic/esp32_https_server/archive/3223704846752e6d545139204837bdb2a55459ca.zip
# renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino
h2zero/NimBLE-Arduino@^1.4.3
# renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master
https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip
# renovate: datasource=github-tags depName=XPowersLib packageName=lewisxhe/XPowersLib
https://github.com/lewisxhe/XPowersLib/archive/v0.3.2.zip
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0

View File

@@ -10,6 +10,8 @@ custom_meshtastic_tags = M5Stack
extends = esp32c6_base
board = esp32-c6-devkitc-1
board_upload.flash_size = 16MB
board_build.partitions = default_16MB.csv
;OpenOCD flash method
;upload_protocol = esp-builtin
;Normal method

View File

@@ -0,0 +1,21 @@
; Russell is a board designed to mount on an ER34615/IFR32700 cell and go Up! on a balloon
; Hardware repository: https://github.com/Meshtastic-Malaysia/russell
; - RAK3172 STM32WLE5CCU6 MCU + integrated SX1262 LoRa
; - CDtop CD-PA1010D GPS
; - Bosch Sensortec BME280 sensor
; - Consonance CN3158 LiFePO4 solar charger
[env:russell]
extends = stm32_base
board = wiscore_rak3172
board_level = extra
board_upload.maximum_size = 233472 ; reserve the last 28KB for filesystem
build_flags =
${stm32_base.build_flags}
-Ivariants/stm32/russell
-DPRIVATE_HW
lib_deps =
${stm32_base.lib_deps}
# renovate: datasource=custom.pio depName=Adafruit BME280 packageName=adafruit/library/Adafruit BME280 Library
adafruit/Adafruit BME280 Library@2.3.0
upload_port = stlink

View File

@@ -0,0 +1,7 @@
// Pins from https://forum.rakwireless.com/t/rak3172-internal-schematic/4557/2
// PB8, PC13
static const RADIOLIB_PIN_TYPE rfswitch_pins[5] = {PB8, PC13, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
static const Module::RfSwitchMode_t rfswitch_table[4] = {
{STM32WLx::MODE_IDLE, {LOW, LOW}}, {STM32WLx::MODE_RX, {HIGH, LOW}}, {STM32WLx::MODE_TX_HP, {LOW, HIGH}}, END_OF_MODE_TABLE};

View File

@@ -0,0 +1,41 @@
#ifndef _VARIANT_RUSSELL_
#define _VARIANT_RUSSELL_
#define USE_STM32WLx
// I/O
#define LED_PIN PA0 // Red LED
#define LED_STATE_ON 1
#define BUTTON_PIN PH3 // Shared with BOOT0
#define BUTTON_NEED_PULLUP
// Charger IC charge/standby pins are open-drain with no hardware pull-up:
// Internal pull-up is needed on STM32 (TODO)
// #define EXT_CHRG_DETECT PA5
// #define EXT_PWR_DETECT PA4
// Bosch Sensortec BME280
#define HAS_SENSOR 1
// CDtop CD-PA1010D
#define ENABLE_HWSERIAL1
#define PIN_SERIAL1_RX PB7
#define PIN_SERIAL1_TX PB6
#define HAS_GPS 1
#define PIN_GPS_STANDBY PA15
#define GPS_RX_PIN PB7
#define GPS_TX_PIN PB6
// LoRa
/*
* RAK3172 (-2085°C) -> No TCXO
* RAK3172-T (-4085°C) -> 3.0V TCXO
* https://github.com/RAKWireless/RAK-STM32-RUI/blob/e5a28be8fab1a492bd9223dd425ca33a8a297d90/variants/WisDuo_RAK3172-T_Board/radio_conf.h#L91
*/
#define TCXO_OPTIONAL
#define SX126X_DIO3_TCXO_VOLTAGE 3.0
// Required to avoid Serial1 conflicts due to board definition here:
// https://github.com/stm32duino/Arduino_Core_STM32/blob/main/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/variant_RAK3172_MODULE.h
#define RAK3172
#endif