mirror of
https://github.com/meshtastic/firmware.git
synced 2025-10-29 15:46:46 +00:00
Merge branch 'meshtastic:develop' into develop
This commit is contained in:
commit
566f6a85e9
@ -9,7 +9,7 @@ plugins:
|
||||
lint:
|
||||
enabled:
|
||||
- checkov@3.2.471
|
||||
- renovate@41.127.2
|
||||
- renovate@41.130.1
|
||||
- prettier@3.6.2
|
||||
- trufflehog@3.90.8
|
||||
- yamllint@1.37.1
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit 46b81e822af1b8e408f437092337f129dee693e6
|
||||
Subproject commit 082bb7cfeb2cba9d41be139cd324c4b43a14b3f9
|
||||
@ -26,6 +26,7 @@ class AudioThread : public concurrency::OSThread
|
||||
i2sRtttl->begin(rtttlFile, audioOut);
|
||||
}
|
||||
|
||||
// Also handles actually playing the RTTTL, needs to be called in loop
|
||||
bool isPlaying()
|
||||
{
|
||||
if (i2sRtttl != nullptr) {
|
||||
|
||||
@ -284,7 +284,7 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
||||
int iconX = iconRightEdge - mute_symbol_big_width;
|
||||
int iconY = textY + (FONT_HEIGHT_SMALL - mute_symbol_big_height) / 2;
|
||||
|
||||
if (isInverted) {
|
||||
if (isInverted && !force_no_invert) {
|
||||
display->setColor(WHITE);
|
||||
display->fillRect(iconX - 1, iconY - 1, mute_symbol_big_width + 2, mute_symbol_big_height + 2);
|
||||
display->setColor(BLACK);
|
||||
|
||||
@ -852,24 +852,31 @@ void menuHandler::GPSFormatMenu()
|
||||
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||
if (selected == 1) {
|
||||
uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_DEC;
|
||||
saveUIConfig();
|
||||
service->reloadConfig(SEGMENT_CONFIG);
|
||||
} else if (selected == 2) {
|
||||
uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_DMS;
|
||||
saveUIConfig();
|
||||
service->reloadConfig(SEGMENT_CONFIG);
|
||||
} else if (selected == 3) {
|
||||
uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_UTM;
|
||||
saveUIConfig();
|
||||
service->reloadConfig(SEGMENT_CONFIG);
|
||||
} else if (selected == 4) {
|
||||
uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_MGRS;
|
||||
saveUIConfig();
|
||||
service->reloadConfig(SEGMENT_CONFIG);
|
||||
} else if (selected == 5) {
|
||||
uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_OLC;
|
||||
saveUIConfig();
|
||||
service->reloadConfig(SEGMENT_CONFIG);
|
||||
} else if (selected == 6) {
|
||||
uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_OSGR;
|
||||
saveUIConfig();
|
||||
service->reloadConfig(SEGMENT_CONFIG);
|
||||
} else if (selected == 7) {
|
||||
uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_MLS;
|
||||
saveUIConfig();
|
||||
service->reloadConfig(SEGMENT_CONFIG);
|
||||
} else {
|
||||
menuQueue = position_base_menu;
|
||||
|
||||
@ -125,8 +125,10 @@ void UIRenderer::drawGpsCoordinates(OLEDDisplay *display, int16_t x, int16_t y,
|
||||
char displayLine[32];
|
||||
|
||||
if (!gps->getIsConnected() && !config.position.fixed_position) {
|
||||
strcpy(displayLine, "No GPS present");
|
||||
display->drawString(x, y, displayLine);
|
||||
if (strcmp(mode, "line1") == 0) {
|
||||
strcpy(displayLine, "No GPS present");
|
||||
display->drawString(x, y, displayLine);
|
||||
}
|
||||
} else if (!gps->getHasLock() && !config.position.fixed_position) {
|
||||
if (strcmp(mode, "line1") == 0) {
|
||||
strcpy(displayLine, "No GPS Lock");
|
||||
@ -1103,6 +1105,18 @@ void UIRenderer::drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayU
|
||||
// === Fourth Row: Line 2 GPS Info ===
|
||||
UIRenderer::drawGpsCoordinates(display, x, getTextPositions(display)[line++], gpsStatus, "line2");
|
||||
}
|
||||
|
||||
// === Final Row: Altitude ===
|
||||
char altitudeLine[32] = {0};
|
||||
int32_t alt = (strcmp(displayLine, "Phone GPS") == 0 && ourNode && nodeDB->hasValidPosition(ourNode))
|
||||
? ourNode->position.altitude
|
||||
: geoCoord.getAltitude();
|
||||
if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL) {
|
||||
snprintf(altitudeLine, sizeof(altitudeLine), "Alt: %.0fft", alt * METERS_TO_FEET);
|
||||
} else {
|
||||
snprintf(altitudeLine, sizeof(altitudeLine), "Alt: %.0im", alt);
|
||||
}
|
||||
display->drawString(x, getTextPositions(display)[line++], altitudeLine);
|
||||
}
|
||||
#if !defined(M5STACK_UNITC6L)
|
||||
// === Draw Compass if heading is valid ===
|
||||
|
||||
@ -701,7 +701,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
||||
#ifdef USERPREFS_NETWORK_ENABLED_PROTOCOLS
|
||||
config.network.enabled_protocols = USERPREFS_NETWORK_ENABLED_PROTOCOLS;
|
||||
#else
|
||||
config.network.enabled_protocols = 1;
|
||||
config.network.enabled_protocols = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -1667,9 +1667,6 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
|
||||
return false;
|
||||
}
|
||||
LOG_INFO("Public Key set for node, not updating!");
|
||||
// we copy the key into the incoming packet, to prevent overwrite
|
||||
p.public_key.size = 32;
|
||||
memcpy(p.public_key.bytes, info->user.public_key.bytes, 32);
|
||||
} else if (p.public_key.size == 32) {
|
||||
LOG_INFO("Update Node Pubkey!");
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ bool Router::shouldDecrementHopLimit(const meshtastic_MeshPacket *p)
|
||||
// For subsequent hops, check if previous relay is a favorite router
|
||||
// Optimized search for favorite routers with matching last byte
|
||||
// Check ordering optimized for IoT devices (cheapest checks first)
|
||||
for (int i = 0; i < nodeDB->getNumMeshNodes(); i++) {
|
||||
for (size_t i = 0; i < nodeDB->getNumMeshNodes(); i++) {
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNodeByIndex(i);
|
||||
if (!node)
|
||||
continue;
|
||||
@ -105,7 +105,7 @@ bool Router::shouldDecrementHopLimit(const meshtastic_MeshPacket *p)
|
||||
|
||||
// Check 3: role check (moderate cost - multiple comparisons)
|
||||
if (!IS_ONE_OF(node->user.role, meshtastic_Config_DeviceConfig_Role_ROUTER,
|
||||
meshtastic_Config_DeviceConfig_Role_ROUTER_LATE, meshtastic_Config_DeviceConfig_Role_CLIENT_BASE)) {
|
||||
meshtastic_Config_DeviceConfig_Role_ROUTER_LATE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -483,35 +483,6 @@ DecodeState perhapsDecode(meshtastic_MeshPacket *p)
|
||||
}
|
||||
}
|
||||
|
||||
#if HAS_UDP_MULTICAST
|
||||
// Fallback: for UDP multicast, try default preset names with default PSK if normal channel match failed
|
||||
if (!decrypted && p->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP) {
|
||||
if (channels.setDefaultPresetCryptoForHash(p->channel)) {
|
||||
memcpy(bytes, p->encrypted.bytes, rawSize);
|
||||
crypto->decrypt(p->from, p->id, rawSize, bytes);
|
||||
|
||||
meshtastic_Data decodedtmp;
|
||||
memset(&decodedtmp, 0, sizeof(decodedtmp));
|
||||
if (pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &decodedtmp) &&
|
||||
decodedtmp.portnum != meshtastic_PortNum_UNKNOWN_APP) {
|
||||
p->decoded = decodedtmp;
|
||||
p->which_payload_variant = meshtastic_MeshPacket_decoded_tag;
|
||||
// Map to our local default channel index (name+PSK default), not necessarily primary
|
||||
ChannelIndex defaultIndex = channels.getPrimaryIndex();
|
||||
for (ChannelIndex i = 0; i < channels.getNumChannels(); ++i) {
|
||||
if (channels.isDefaultChannel(i)) {
|
||||
defaultIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
chIndex = defaultIndex;
|
||||
decrypted = true;
|
||||
} else {
|
||||
LOG_WARN("UDP fallback decode attempted but failed for hash 0x%x", p->channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (decrypted) {
|
||||
// parsing was successful
|
||||
p->channel = chIndex; // change to store the index instead of the hash
|
||||
|
||||
@ -55,7 +55,7 @@ extern const pb_msgdesc_t meshtastic_ChannelSet_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_APPONLY_PB_H_MAX_SIZE meshtastic_ChannelSet_size
|
||||
#define meshtastic_ChannelSet_size 679
|
||||
#define meshtastic_ChannelSet_size 695
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@ -97,6 +97,8 @@ typedef struct _meshtastic_ChannelSettings {
|
||||
/* Per-channel module settings. */
|
||||
bool has_module_settings;
|
||||
meshtastic_ModuleSettings module_settings;
|
||||
/* Whether or not we should receive notifactions / alerts through this channel */
|
||||
bool mute;
|
||||
} meshtastic_ChannelSettings;
|
||||
|
||||
/* A pair of a channel number, mode and the (sharable) settings for that channel */
|
||||
@ -128,10 +130,10 @@ extern "C" {
|
||||
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_ChannelSettings_init_default {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_default}
|
||||
#define meshtastic_ChannelSettings_init_default {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_default, 0}
|
||||
#define meshtastic_ModuleSettings_init_default {0, 0}
|
||||
#define meshtastic_Channel_init_default {0, false, meshtastic_ChannelSettings_init_default, _meshtastic_Channel_Role_MIN}
|
||||
#define meshtastic_ChannelSettings_init_zero {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_zero}
|
||||
#define meshtastic_ChannelSettings_init_zero {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_zero, 0}
|
||||
#define meshtastic_ModuleSettings_init_zero {0, 0}
|
||||
#define meshtastic_Channel_init_zero {0, false, meshtastic_ChannelSettings_init_zero, _meshtastic_Channel_Role_MIN}
|
||||
|
||||
@ -145,6 +147,7 @@ extern "C" {
|
||||
#define meshtastic_ChannelSettings_uplink_enabled_tag 5
|
||||
#define meshtastic_ChannelSettings_downlink_enabled_tag 6
|
||||
#define meshtastic_ChannelSettings_module_settings_tag 7
|
||||
#define meshtastic_ChannelSettings_mute_tag 8
|
||||
#define meshtastic_Channel_index_tag 1
|
||||
#define meshtastic_Channel_settings_tag 2
|
||||
#define meshtastic_Channel_role_tag 3
|
||||
@ -157,7 +160,8 @@ X(a, STATIC, SINGULAR, STRING, name, 3) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, id, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, uplink_enabled, 5) \
|
||||
X(a, STATIC, SINGULAR, BOOL, downlink_enabled, 6) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, module_settings, 7)
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, module_settings, 7) \
|
||||
X(a, STATIC, SINGULAR, BOOL, mute, 8)
|
||||
#define meshtastic_ChannelSettings_CALLBACK NULL
|
||||
#define meshtastic_ChannelSettings_DEFAULT NULL
|
||||
#define meshtastic_ChannelSettings_module_settings_MSGTYPE meshtastic_ModuleSettings
|
||||
@ -187,8 +191,8 @@ extern const pb_msgdesc_t meshtastic_Channel_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_CHANNEL_PB_H_MAX_SIZE meshtastic_Channel_size
|
||||
#define meshtastic_ChannelSettings_size 72
|
||||
#define meshtastic_Channel_size 87
|
||||
#define meshtastic_ChannelSettings_size 74
|
||||
#define meshtastic_Channel_size 89
|
||||
#define meshtastic_ModuleSettings_size 8
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -26,7 +26,8 @@ typedef enum _meshtastic_Config_DeviceConfig_Role {
|
||||
meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT = 3,
|
||||
/* Description: Infrastructure node for extending network coverage by relaying messages with minimal overhead. Not visible in Nodes list.
|
||||
Technical Details: Mesh packets will simply be rebroadcasted over this node. Nodes configured with this role will not originate NodeInfo, Position, Telemetry
|
||||
or any other packet type. They will simply rebroadcast any mesh packets on the same frequency, channel num, spread factor, and coding rate. */
|
||||
or any other packet type. They will simply rebroadcast any mesh packets on the same frequency, channel num, spread factor, and coding rate.
|
||||
Deprecated in v2.7.11 because it creates "holes" in the mesh rebroadcast chain. */
|
||||
meshtastic_Config_DeviceConfig_Role_REPEATER = 4,
|
||||
/* Description: Broadcasts GPS position packets as priority.
|
||||
Technical Details: Position Mesh packets will be prioritized higher and sent more frequently by default.
|
||||
|
||||
@ -360,8 +360,8 @@ 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 2277
|
||||
#define meshtastic_ChannelFile_size 718
|
||||
#define meshtastic_BackupPreferences_size 2293
|
||||
#define meshtastic_ChannelFile_size 734
|
||||
#define meshtastic_DeviceState_size 1737
|
||||
#define meshtastic_NodeInfoLite_size 196
|
||||
#define meshtastic_PositionLite_size 28
|
||||
|
||||
@ -89,11 +89,12 @@ int32_t ExternalNotificationModule::runOnce()
|
||||
return INT32_MAX; // we don't need this thread here...
|
||||
} else {
|
||||
uint32_t delay = EXT_NOTIFICATION_MODULE_OUTPUT_MS;
|
||||
bool isPlaying = rtttl::isPlaying();
|
||||
bool isRtttlPlaying = rtttl::isPlaying();
|
||||
#ifdef HAS_I2S
|
||||
isPlaying = rtttl::isPlaying() || audioThread->isPlaying();
|
||||
// audioThread->isPlaying() also handles actually playing the RTTTL, needs to be called in loop
|
||||
isRtttlPlaying = isRtttlPlaying || audioThread->isPlaying();
|
||||
#endif
|
||||
if ((nagCycleCutoff < millis()) && !isPlaying) {
|
||||
if ((nagCycleCutoff < millis()) && !isRtttlPlaying) {
|
||||
// let the song finish if we reach timeout
|
||||
nagCycleCutoff = UINT32_MAX;
|
||||
LOG_INFO("Turning off external notification: ");
|
||||
@ -187,12 +188,14 @@ int32_t ExternalNotificationModule::runOnce()
|
||||
|
||||
// Play RTTTL over i2s audio interface if enabled as buzzer
|
||||
#ifdef HAS_I2S
|
||||
if (moduleConfig.external_notification.use_i2s_as_buzzer && canBuzz()) {
|
||||
if (moduleConfig.external_notification.use_i2s_as_buzzer) {
|
||||
if (audioThread->isPlaying()) {
|
||||
// Continue playing
|
||||
} else if (isNagging && (nagCycleCutoff >= millis())) {
|
||||
audioThread->beginRttl(rtttlConfig.ringtone, strlen_P(rtttlConfig.ringtone));
|
||||
}
|
||||
// we need fast updates to play the RTTTL
|
||||
delay = EXT_NOTIFICATION_FAST_THREAD_MS;
|
||||
}
|
||||
#endif
|
||||
// now let the PWM buzzer play
|
||||
|
||||
@ -41,12 +41,12 @@ int32_t RangeTestModule::runOnce()
|
||||
// moduleConfig.range_test.enabled = 1;
|
||||
// moduleConfig.range_test.sender = 30;
|
||||
// moduleConfig.range_test.save = 1;
|
||||
// moduleConfig.range_test.clear_on_reboot = 1;
|
||||
|
||||
// Fixed position is useful when testing indoors.
|
||||
// config.position.fixed_position = 1;
|
||||
|
||||
uint32_t senderHeartbeat = moduleConfig.range_test.sender * 1000;
|
||||
|
||||
if (moduleConfig.range_test.enabled) {
|
||||
|
||||
if (firstTime) {
|
||||
@ -54,6 +54,11 @@ int32_t RangeTestModule::runOnce()
|
||||
|
||||
firstTime = 0;
|
||||
|
||||
if (moduleConfig.range_test.clear_on_reboot) {
|
||||
// User wants to delete previous range test(s)
|
||||
LOG_INFO("Range Test Module - Clearing out previous test file");
|
||||
rangeTestModuleRadio->removeFile();
|
||||
}
|
||||
if (moduleConfig.range_test.sender) {
|
||||
LOG_INFO("Init Range Test Module -- Sender");
|
||||
started = millis(); // make a note of when we started
|
||||
@ -141,7 +146,6 @@ ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket
|
||||
*/
|
||||
|
||||
if (!isFromUs(&mp)) {
|
||||
|
||||
if (moduleConfig.range_test.save) {
|
||||
appendFile(mp);
|
||||
}
|
||||
@ -295,7 +299,42 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp)
|
||||
fileToAppend.printf("\"%s\"\n", p.payload.bytes);
|
||||
fileToAppend.flush();
|
||||
fileToAppend.close();
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
|
||||
#else
|
||||
LOG_ERROR("Failed to store range test results - feature only available for ESP32");
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool RangeTestModuleRadio::removeFile()
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
if (!FSBegin()) {
|
||||
LOG_DEBUG("An Error has occurred while mounting the filesystem");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!FSCom.exists("/static/rangetest.csv")) {
|
||||
LOG_DEBUG("No range tests found.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_INFO("Deleting previous range test.");
|
||||
bool result = FSCom.remove("/static/rangetest.csv");
|
||||
|
||||
if (!result) {
|
||||
LOG_ERROR("Failed to delete range test.");
|
||||
return 0;
|
||||
}
|
||||
LOG_INFO("Range test removed.");
|
||||
|
||||
return 1;
|
||||
#else
|
||||
LOG_ERROR("Failed to remove range test results - feature only available for ESP32");
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@ -44,6 +44,11 @@ class RangeTestModuleRadio : public SinglePortModule
|
||||
*/
|
||||
bool appendFile(const meshtastic_MeshPacket &mp);
|
||||
|
||||
/**
|
||||
* Cleanup range test data from filesystem
|
||||
*/
|
||||
bool removeFile();
|
||||
|
||||
protected:
|
||||
/** Called to handle a particular incoming message
|
||||
|
||||
|
||||
@ -224,7 +224,7 @@ extern struct portduino_config_struct {
|
||||
out << YAML::Key << "RF95_MAX_POWER" << YAML::Value << rf95_max_power;
|
||||
out << YAML::Key << "DIO2_AS_RF_SWITCH" << YAML::Value << dio2_as_rf_switch;
|
||||
if (dio3_tcxo_voltage != 0)
|
||||
out << YAML::Key << "DIO3_TCXO_VOLTAGE" << YAML::Value << dio3_tcxo_voltage;
|
||||
out << YAML::Key << "DIO3_TCXO_VOLTAGE" << YAML::Value << YAML::Precision(3) << (float)dio3_tcxo_voltage / 1000;
|
||||
if (lora_usb_pid != 0x5512)
|
||||
out << YAML::Key << "USB_PID" << YAML::Value << YAML::Hex << lora_usb_pid;
|
||||
if (lora_usb_vid != 0x1A86)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user