mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-29 22:20:37 +00:00
Resolve merge conflict
This commit is contained in:
@@ -13,12 +13,16 @@
|
||||
#include "detect/ScanI2C.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "graphics/SharedUIDisplay.h"
|
||||
#include "graphics/draw/NotificationRenderer.h"
|
||||
#include "graphics/emotes.h"
|
||||
#include "graphics/images.h"
|
||||
#include "main.h" // for cardkb_found
|
||||
#include "mesh/generated/meshtastic/cannedmessages.pb.h"
|
||||
#include "modules/AdminModule.h"
|
||||
#include "modules/ExternalNotificationModule.h" // for buzzer control
|
||||
#if HAS_TRACKBALL
|
||||
#include "input/TrackballInterruptImpl1.h"
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "GPS.h"
|
||||
#endif
|
||||
@@ -38,6 +42,7 @@
|
||||
|
||||
extern ScanI2C::DeviceAddress cardkb_found;
|
||||
extern bool graphics::isMuted;
|
||||
extern bool osk_found;
|
||||
|
||||
static const char *cannedMessagesConfigFile = "/prefs/cannedConf.proto";
|
||||
static NodeNum lastDest = NODENUM_BROADCAST;
|
||||
@@ -78,16 +83,15 @@ void CannedMessageModule::LaunchWithDestination(NodeNum newDest, uint8_t newChan
|
||||
lastDestSet = true;
|
||||
|
||||
// Rest of function unchanged...
|
||||
// Always select the first real canned message on activation
|
||||
int firstRealMsgIdx = 0;
|
||||
// Upon activation, highlight "[Select Destination]"
|
||||
int selectDestination = 0;
|
||||
for (int i = 0; i < messagesCount; ++i) {
|
||||
if (strcmp(messages[i], "[Select Destination]") != 0 && strcmp(messages[i], "[Exit]") != 0 &&
|
||||
strcmp(messages[i], "[---- Free Text ----]") != 0) {
|
||||
firstRealMsgIdx = i;
|
||||
if (strcmp(messages[i], "[Select Destination]") == 0) {
|
||||
selectDestination = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
currentMessageIndex = firstRealMsgIdx;
|
||||
currentMessageIndex = selectDestination;
|
||||
|
||||
// This triggers the canned message list
|
||||
runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
|
||||
@@ -152,10 +156,13 @@ int CannedMessageModule::splitConfiguredMessages()
|
||||
int tempCount = 0;
|
||||
// Insert at position 0 (top)
|
||||
tempMessages[tempCount++] = "[Select Destination]";
|
||||
|
||||
#if defined(USE_VIRTUAL_KEYBOARD)
|
||||
// Add a "Free Text" entry at the top if using a keyboard
|
||||
// Add a "Free Text" entry at the top if using a touch screen virtual keyboard
|
||||
tempMessages[tempCount++] = "[-- Free Text --]";
|
||||
#else
|
||||
if (osk_found && screen) {
|
||||
tempMessages[tempCount++] = "[-- Free Text --]";
|
||||
}
|
||||
#endif
|
||||
|
||||
// First message always starts at buffer start
|
||||
@@ -342,6 +349,8 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
case CANNED_MESSAGE_RUN_STATE_FREETEXT:
|
||||
return handleFreeTextInput(event); // All allowed input for this state
|
||||
|
||||
// Virtual keyboard mode: Show virtual keyboard and handle input
|
||||
|
||||
// If sending, block all input except global/system (handled above)
|
||||
case CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE:
|
||||
return 1;
|
||||
@@ -628,6 +637,56 @@ bool CannedMessageModule::handleMessageSelectorInput(const InputEvent *event, bo
|
||||
notifyObservers(&e);
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
if (strcmp(current, "[-- Free Text --]") == 0) {
|
||||
if (osk_found && screen) {
|
||||
char headerBuffer[64];
|
||||
if (this->dest == NODENUM_BROADCAST) {
|
||||
snprintf(headerBuffer, sizeof(headerBuffer), "To: Broadcast@%s", channels.getName(this->channel));
|
||||
} else {
|
||||
snprintf(headerBuffer, sizeof(headerBuffer), "To: %s", getNodeName(this->dest));
|
||||
}
|
||||
screen->showTextInput(headerBuffer, "", 300000, [this](const std::string &text) {
|
||||
if (!text.empty()) {
|
||||
this->freetext = text.c_str();
|
||||
this->payload = CANNED_MESSAGE_RUN_STATE_FREETEXT;
|
||||
runState = CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE;
|
||||
currentMessageIndex = -1;
|
||||
|
||||
UIFrameEvent e;
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||
this->notifyObservers(&e);
|
||||
screen->forceDisplay();
|
||||
|
||||
setIntervalFromNow(500);
|
||||
return;
|
||||
} else {
|
||||
// Don't delete virtual keyboard immediately - it might still be executing
|
||||
// Instead, just clear the callback and reset banner to stop input processing
|
||||
graphics::NotificationRenderer::textInputCallback = nullptr;
|
||||
graphics::NotificationRenderer::resetBanner();
|
||||
|
||||
// Return to inactive state
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
this->currentMessageIndex = -1;
|
||||
this->freetext = "";
|
||||
this->cursor = 0;
|
||||
|
||||
// Force display update to show normal screen
|
||||
UIFrameEvent e;
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||
this->notifyObservers(&e);
|
||||
screen->forceDisplay();
|
||||
|
||||
// Schedule cleanup for next loop iteration to ensure safe deletion
|
||||
setIntervalFromNow(50);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Normal canned message selection
|
||||
@@ -944,12 +1003,54 @@ int32_t CannedMessageModule::runOnce()
|
||||
|
||||
// Normal module disable/idle handling
|
||||
if ((this->runState == CANNED_MESSAGE_RUN_STATE_DISABLED) || (this->runState == CANNED_MESSAGE_RUN_STATE_INACTIVE)) {
|
||||
// Clean up virtual keyboard if needed when going inactive
|
||||
if (graphics::NotificationRenderer::virtualKeyboard && graphics::NotificationRenderer::textInputCallback == nullptr) {
|
||||
LOG_INFO("Performing delayed virtual keyboard cleanup");
|
||||
delete graphics::NotificationRenderer::virtualKeyboard;
|
||||
graphics::NotificationRenderer::virtualKeyboard = nullptr;
|
||||
}
|
||||
|
||||
temporaryMessage = "";
|
||||
return INT32_MAX;
|
||||
}
|
||||
|
||||
// Handle delayed virtual keyboard message sending
|
||||
if (this->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE && this->payload == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
||||
// Virtual keyboard message sending case - text was not empty
|
||||
if (this->freetext.length() > 0) {
|
||||
LOG_INFO("Processing delayed virtual keyboard send: '%s'", this->freetext.c_str());
|
||||
sendText(this->dest, this->channel, this->freetext.c_str(), true);
|
||||
|
||||
// Clean up virtual keyboard after sending
|
||||
if (graphics::NotificationRenderer::virtualKeyboard) {
|
||||
LOG_INFO("Cleaning up virtual keyboard after message send");
|
||||
delete graphics::NotificationRenderer::virtualKeyboard;
|
||||
graphics::NotificationRenderer::virtualKeyboard = nullptr;
|
||||
graphics::NotificationRenderer::textInputCallback = nullptr;
|
||||
graphics::NotificationRenderer::resetBanner();
|
||||
}
|
||||
|
||||
// Clear payload to indicate virtual keyboard processing is complete
|
||||
// But keep SENDING_ACTIVE state to show "Sending..." screen for 2 seconds
|
||||
this->payload = 0;
|
||||
} else {
|
||||
// Empty message, just go inactive
|
||||
LOG_INFO("Empty freetext detected in delayed processing, returning to inactive state");
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
}
|
||||
|
||||
UIFrameEvent e;
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||
this->currentMessageIndex = -1;
|
||||
this->freetext = "";
|
||||
this->cursor = 0;
|
||||
this->notifyObservers(&e);
|
||||
return 2000;
|
||||
}
|
||||
|
||||
UIFrameEvent e;
|
||||
if ((this->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) ||
|
||||
if ((this->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE && this->payload != 0 &&
|
||||
this->payload != CANNED_MESSAGE_RUN_STATE_FREETEXT) ||
|
||||
(this->runState == CANNED_MESSAGE_RUN_STATE_ACK_NACK_RECEIVED) ||
|
||||
(this->runState == CANNED_MESSAGE_RUN_STATE_MESSAGE_SELECTION)) {
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
@@ -959,6 +1060,18 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->freetext = "";
|
||||
this->cursor = 0;
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
// Handle SENDING_ACTIVE state transition after virtual keyboard message
|
||||
else if (this->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE && this->payload == 0) {
|
||||
// This happens after virtual keyboard message sending is complete
|
||||
LOG_INFO("Virtual keyboard message sending completed, returning to inactive state");
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
temporaryMessage = "";
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||
this->currentMessageIndex = -1;
|
||||
this->freetext = "";
|
||||
this->cursor = 0;
|
||||
this->notifyObservers(&e);
|
||||
} else if (((this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT)) &&
|
||||
!Throttle::isWithinTimespanMs(this->lastTouchMillis, INACTIVATE_AFTER_MS)) {
|
||||
// Reset module on inactivity
|
||||
@@ -967,9 +1080,23 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->freetext = "";
|
||||
this->cursor = 0;
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
|
||||
// Clean up virtual keyboard if it exists during timeout
|
||||
if (graphics::NotificationRenderer::virtualKeyboard) {
|
||||
LOG_INFO("Cleaning up virtual keyboard due to module timeout");
|
||||
delete graphics::NotificationRenderer::virtualKeyboard;
|
||||
graphics::NotificationRenderer::virtualKeyboard = nullptr;
|
||||
graphics::NotificationRenderer::textInputCallback = nullptr;
|
||||
graphics::NotificationRenderer::resetBanner();
|
||||
}
|
||||
|
||||
this->notifyObservers(&e);
|
||||
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_SELECT) {
|
||||
if (this->payload == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
||||
if (this->payload == 0) {
|
||||
// [Exit] button pressed - return to inactive state
|
||||
LOG_INFO("Processing [Exit] action - returning to inactive state");
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
} else if (this->payload == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
||||
if (this->freetext.length() > 0) {
|
||||
sendText(this->dest, this->channel, this->freetext.c_str(), true);
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE;
|
||||
@@ -999,17 +1126,16 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->notifyObservers(&e);
|
||||
return 2000;
|
||||
}
|
||||
// Always highlight the first real canned message when entering the message list
|
||||
// Highlight [Select Destination] initially when entering the message list
|
||||
else if ((this->runState != CANNED_MESSAGE_RUN_STATE_FREETEXT) && (this->currentMessageIndex == -1)) {
|
||||
int firstRealMsgIdx = 0;
|
||||
int selectDestination = 0;
|
||||
for (int i = 0; i < this->messagesCount; ++i) {
|
||||
if (strcmp(this->messages[i], "[Select Destination]") != 0 && strcmp(this->messages[i], "[Exit]") != 0 &&
|
||||
strcmp(this->messages[i], "[---- Free Text ----]") != 0) {
|
||||
firstRealMsgIdx = i;
|
||||
if (strcmp(this->messages[i], "[Select Destination]") == 0) {
|
||||
selectDestination = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->currentMessageIndex = firstRealMsgIdx;
|
||||
this->currentMessageIndex = selectDestination;
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
|
||||
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_UP) {
|
||||
|
||||
@@ -14,6 +14,10 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
|
||||
{
|
||||
auto p = *pptr;
|
||||
|
||||
if (mp.from == nodeDB->getNodeNum()) {
|
||||
LOG_WARN("Ignoring packet supposed to be from our own node: %08x", mp.from);
|
||||
return false;
|
||||
}
|
||||
if (p.is_licensed != owner.is_licensed) {
|
||||
LOG_WARN("Invalid nodeInfo detected, is_licensed mismatch!");
|
||||
return true;
|
||||
|
||||
@@ -73,7 +73,7 @@ uint8_t RoutingModule::getHopLimitForResponse(uint8_t hopStart, uint8_t hopLimit
|
||||
return Default::getConfiguredOrDefaultHopLimit(config.lora.hop_limit); // Use the default hop limit
|
||||
}
|
||||
|
||||
RoutingModule::RoutingModule() : ProtobufModule("routing", meshtastic_PortNum_ROUTING_APP, &meshtastic_Routing_msg)
|
||||
RoutingModule::RoutingModule() : ProtobufModule(ROUTING_MODULE, meshtastic_PortNum_ROUTING_APP, &meshtastic_Routing_msg)
|
||||
{
|
||||
isPromiscuous = true;
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#include "Channels.h"
|
||||
#include "ProtobufModule.h"
|
||||
|
||||
static const char *ROUTING_MODULE = "routing";
|
||||
|
||||
/**
|
||||
* Routing module for router control messages
|
||||
*/
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
SerialModule *serialModule;
|
||||
SerialModuleRadio *serialModuleRadio;
|
||||
|
||||
#if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1) || \
|
||||
#if defined(TTGO_T_ECHO) || defined(T_ECHO_LITE) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1) || \
|
||||
defined(ELECROW_ThinkNode_M5)
|
||||
SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial") {}
|
||||
static Print *serialPrint = &Serial;
|
||||
@@ -179,8 +179,8 @@ int32_t SerialModule::runOnce()
|
||||
Serial.begin(baud);
|
||||
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
|
||||
}
|
||||
#elif !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && \
|
||||
!defined(ELECROW_ThinkNode_M5)
|
||||
#elif !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
|
||||
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
|
||||
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
|
||||
#ifdef ARCH_RP2040
|
||||
Serial2.setFIFOSize(RX_BUFFER);
|
||||
@@ -236,8 +236,8 @@ int32_t SerialModule::runOnce()
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && \
|
||||
!defined(ELECROW_ThinkNode_M5)
|
||||
#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
|
||||
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
|
||||
else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) {
|
||||
processWXSerial();
|
||||
|
||||
@@ -496,8 +496,8 @@ ParsedLine parseLine(const char *line)
|
||||
*/
|
||||
void SerialModule::processWXSerial()
|
||||
{
|
||||
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(MESHLINK) && \
|
||||
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
|
||||
#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && \
|
||||
!defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
|
||||
static unsigned int lastAveraged = 0;
|
||||
static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded.
|
||||
static double dir_sum_sin = 0;
|
||||
|
||||
@@ -602,7 +602,7 @@ void TraceRouteModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state
|
||||
int start = 0;
|
||||
int newlinePos = resultText.indexOf('\n', start);
|
||||
|
||||
while (newlinePos != -1 || start < resultText.length()) {
|
||||
while (newlinePos != -1 || start < static_cast<int>(resultText.length())) {
|
||||
String segment;
|
||||
if (newlinePos != -1) {
|
||||
segment = resultText.substring(start, newlinePos);
|
||||
@@ -624,7 +624,7 @@ void TraceRouteModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state
|
||||
int lastGoodBreak = -1;
|
||||
bool lineComplete = false;
|
||||
|
||||
for (int i = 0; i < remaining.length(); i++) {
|
||||
for (int i = 0; i < static_cast<int>(remaining.length()); i++) {
|
||||
char ch = remaining.charAt(i);
|
||||
String testLine = tempLine + ch;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user