Select Node and channel in Canned Message module.

This commit is contained in:
Thomas Göttgens 2023-12-11 23:49:33 +01:00 committed by Jonathan Bennett
parent 4b7fbeca29
commit dad05d7873
2 changed files with 77 additions and 22 deletions

View File

@ -4,6 +4,7 @@
#endif #endif
#if HAS_SCREEN #if HAS_SCREEN
#include "CannedMessageModule.h" #include "CannedMessageModule.h"
#include "Channels.h"
#include "FSCommon.h" #include "FSCommon.h"
#include "MeshService.h" #include "MeshService.h"
#include "NodeDB.h" #include "NodeDB.h"
@ -187,10 +188,10 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
if (!event->kbchar) { if (!event->kbchar) {
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) { if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
this->payload = 0xb4; this->payload = 0xb4;
this->destSelect = true; this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NODE;
} else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) { } else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
this->payload = 0xb7; this->payload = 0xb7;
this->destSelect = true; this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NODE;
} }
} else { } else {
// pass the pressed key // pass the pressed key
@ -234,10 +235,11 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
return 0; return 0;
} }
void CannedMessageModule::sendText(NodeNum dest, const char *message, bool wantReplies) void CannedMessageModule::sendText(NodeNum dest, ChannelIndex channel, const char *message, bool wantReplies)
{ {
meshtastic_MeshPacket *p = allocDataPacket(); meshtastic_MeshPacket *p = allocDataPacket();
p->to = dest; p->to = dest;
p->channel = channel;
p->want_ack = true; p->want_ack = true;
p->decoded.payload.size = strlen(message); p->decoded.payload.size = strlen(message);
memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size); memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size);
@ -270,7 +272,7 @@ int32_t CannedMessageModule::runOnce()
this->currentMessageIndex = -1; this->currentMessageIndex = -1;
this->freetext = ""; // clear freetext this->freetext = ""; // clear freetext
this->cursor = 0; this->cursor = 0;
this->destSelect = false; this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
this->notifyObservers(&e); this->notifyObservers(&e);
} else if (((this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT)) && } else if (((this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT)) &&
((millis() - this->lastTouchMillis) > INACTIVATE_AFTER_MS)) { ((millis() - this->lastTouchMillis) > INACTIVATE_AFTER_MS)) {
@ -280,13 +282,13 @@ int32_t CannedMessageModule::runOnce()
this->currentMessageIndex = -1; this->currentMessageIndex = -1;
this->freetext = ""; // clear freetext this->freetext = ""; // clear freetext
this->cursor = 0; this->cursor = 0;
this->destSelect = false; this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE; this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
this->notifyObservers(&e); this->notifyObservers(&e);
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_SELECT) { } else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_SELECT) {
if (this->payload == CANNED_MESSAGE_RUN_STATE_FREETEXT) { if (this->payload == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
if (this->freetext.length() > 0) { if (this->freetext.length() > 0) {
sendText(this->dest, this->freetext.c_str(), true); sendText(this->dest, indexChannels[this->channel], this->freetext.c_str(), true);
this->runState = CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE; this->runState = CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE;
} else { } else {
LOG_DEBUG("Reset message is empty.\n"); LOG_DEBUG("Reset message is empty.\n");
@ -298,7 +300,7 @@ int32_t CannedMessageModule::runOnce()
powerFSM.trigger(EVENT_PRESS); powerFSM.trigger(EVENT_PRESS);
return INT32_MAX; return INT32_MAX;
} else { } else {
sendText(NODENUM_BROADCAST, this->messages[this->currentMessageIndex], true); sendText(NODENUM_BROADCAST, channels.getPrimaryIndex(), this->messages[this->currentMessageIndex], true);
} }
this->runState = CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE; this->runState = CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE;
} else { } else {
@ -310,7 +312,7 @@ int32_t CannedMessageModule::runOnce()
this->currentMessageIndex = -1; this->currentMessageIndex = -1;
this->freetext = ""; // clear freetext this->freetext = ""; // clear freetext
this->cursor = 0; this->cursor = 0;
this->destSelect = false; this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
this->notifyObservers(&e); this->notifyObservers(&e);
return 2000; return 2000;
} else if ((this->runState != CANNED_MESSAGE_RUN_STATE_FREETEXT) && (this->currentMessageIndex == -1)) { } else if ((this->runState != CANNED_MESSAGE_RUN_STATE_FREETEXT) && (this->currentMessageIndex == -1)) {
@ -323,7 +325,7 @@ int32_t CannedMessageModule::runOnce()
this->currentMessageIndex = getPrevIndex(); this->currentMessageIndex = getPrevIndex();
this->freetext = ""; // clear freetext this->freetext = ""; // clear freetext
this->cursor = 0; this->cursor = 0;
this->destSelect = false; this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE; this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
LOG_DEBUG("MOVE UP (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage()); LOG_DEBUG("MOVE UP (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage());
} }
@ -332,14 +334,14 @@ int32_t CannedMessageModule::runOnce()
this->currentMessageIndex = this->getNextIndex(); this->currentMessageIndex = this->getNextIndex();
this->freetext = ""; // clear freetext this->freetext = ""; // clear freetext
this->cursor = 0; this->cursor = 0;
this->destSelect = false; this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE; this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
LOG_DEBUG("MOVE DOWN (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage()); LOG_DEBUG("MOVE DOWN (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage());
} }
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT || this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) { } else if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT || this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) {
switch (this->payload) { switch (this->payload) {
case 0xb4: // left case 0xb4: // left
if (this->destSelect) { if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_NODE) {
size_t numMeshNodes = nodeDB.getNumMeshNodes(); size_t numMeshNodes = nodeDB.getNumMeshNodes();
if (this->dest == NODENUM_BROADCAST) { if (this->dest == NODENUM_BROADCAST) {
this->dest = nodeDB.getNodeNum(); this->dest = nodeDB.getNodeNum();
@ -354,6 +356,19 @@ int32_t CannedMessageModule::runOnce()
if (this->dest == nodeDB.getNodeNum()) { if (this->dest == nodeDB.getNodeNum()) {
this->dest = NODENUM_BROADCAST; this->dest = NODENUM_BROADCAST;
} }
} else if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_CHANNEL) {
for (unsigned int i = 0; i < channels.getNumChannels(); i++) {
if ((channels.getByIndex(i).role == meshtastic_Channel_Role_SECONDARY) ||
(channels.getByIndex(i).role == meshtastic_Channel_Role_PRIMARY)) {
indexChannels[numChannels] = i;
numChannels++;
}
}
if (this->channel == 0) {
this->channel = numChannels - 1;
} else {
this->channel--;
}
} else { } else {
if (this->cursor > 0) { if (this->cursor > 0) {
this->cursor--; this->cursor--;
@ -361,7 +376,7 @@ int32_t CannedMessageModule::runOnce()
} }
break; break;
case 0xb7: // right case 0xb7: // right
if (this->destSelect) { if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_NODE) {
size_t numMeshNodes = nodeDB.getNumMeshNodes(); size_t numMeshNodes = nodeDB.getNumMeshNodes();
if (this->dest == NODENUM_BROADCAST) { if (this->dest == NODENUM_BROADCAST) {
this->dest = nodeDB.getNodeNum(); this->dest = nodeDB.getNodeNum();
@ -376,6 +391,19 @@ int32_t CannedMessageModule::runOnce()
if (this->dest == nodeDB.getNodeNum()) { if (this->dest == nodeDB.getNodeNum()) {
this->dest = NODENUM_BROADCAST; this->dest = NODENUM_BROADCAST;
} }
} else if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_CHANNEL) {
for (unsigned int i = 0; i < channels.getNumChannels(); i++) {
if ((channels.getByIndex(i).role == meshtastic_Channel_Role_SECONDARY) ||
(channels.getByIndex(i).role == meshtastic_Channel_Role_PRIMARY)) {
indexChannels[numChannels] = i;
numChannels++;
}
}
if (this->channel == numChannels - 1) {
this->channel = 0;
} else {
this->channel++;
}
} else { } else {
if (this->cursor < this->freetext.length()) { if (this->cursor < this->freetext.length()) {
this->cursor++; this->cursor++;
@ -400,10 +428,12 @@ int32_t CannedMessageModule::runOnce()
} }
break; break;
case 0x09: // tab case 0x09: // tab
if (this->destSelect) { if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_CHANNEL) {
this->destSelect = false; this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
} else if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_NODE) {
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_CHANNEL;
} else { } else {
this->destSelect = true; this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NODE;
} }
break; break;
case 0xb4: // left case 0xb4: // left
@ -524,18 +554,34 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
} else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) { } else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
display->setTextAlignment(TEXT_ALIGN_LEFT); display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_SMALL); display->setFont(FONT_SMALL);
if (this->destSelect) { if (this->destSelect != CANNED_MESSAGE_DESTINATION_TYPE_NONE) {
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL); display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->setColor(BLACK); display->setColor(BLACK);
display->drawStringf(1 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
} }
display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest)); switch (this->destSelect) {
case CANNED_MESSAGE_DESTINATION_TYPE_NODE:
display->drawStringf(1 + x, 0 + y, buffer, "To: >%s<@%s", cannedMessageModule->getNodeName(this->dest),
channels.getName(indexChannels[this->channel]));
display->drawStringf(0 + x, 0 + y, buffer, "To: >%s<@%s", cannedMessageModule->getNodeName(this->dest),
channels.getName(indexChannels[this->channel]));
break;
case CANNED_MESSAGE_DESTINATION_TYPE_CHANNEL:
display->drawStringf(1 + x, 0 + y, buffer, "To: %s@>%s<", cannedMessageModule->getNodeName(this->dest),
channels.getName(indexChannels[this->channel]));
display->drawStringf(0 + x, 0 + y, buffer, "To: %s@>%s<", cannedMessageModule->getNodeName(this->dest),
channels.getName(indexChannels[this->channel]));
break;
default:
display->drawStringf(0 + x, 0 + y, buffer, "To: %s@%s", cannedMessageModule->getNodeName(this->dest),
channels.getName(indexChannels[this->channel]));
break;
}
// used chars right aligned // used chars right aligned
uint16_t charsLeft = uint16_t charsLeft =
meshtastic_Constants_DATA_PAYLOAD_LEN - this->freetext.length() - (moduleConfig.canned_message.send_bell ? 1 : 0); meshtastic_Constants_DATA_PAYLOAD_LEN - this->freetext.length() - (moduleConfig.canned_message.send_bell ? 1 : 0);
snprintf(buffer, sizeof(buffer), "%d left", charsLeft); snprintf(buffer, sizeof(buffer), "%d left", charsLeft);
display->drawString(x + display->getWidth() - display->getStringWidth(buffer), y + 0, buffer); display->drawString(x + display->getWidth() - display->getStringWidth(buffer), y + 0, buffer);
if (this->destSelect) { if (this->destSelect != CANNED_MESSAGE_DESTINATION_TYPE_NONE) {
display->drawString(x + display->getWidth() - display->getStringWidth(buffer) - 1, y + 0, buffer); display->drawString(x + display->getWidth() - display->getStringWidth(buffer) - 1, y + 0, buffer);
} }
display->setColor(WHITE); display->setColor(WHITE);

View File

@ -15,6 +15,12 @@ enum cannedMessageModuleRunState {
CANNED_MESSAGE_RUN_STATE_ACTION_DOWN, CANNED_MESSAGE_RUN_STATE_ACTION_DOWN,
}; };
enum cannedMessageDestinationType {
CANNED_MESSAGE_DESTINATION_TYPE_NONE,
CANNED_MESSAGE_DESTINATION_TYPE_NODE,
CANNED_MESSAGE_DESTINATION_TYPE_CHANNEL
};
#define CANNED_MESSAGE_MODULE_MESSAGE_MAX_COUNT 50 #define CANNED_MESSAGE_MODULE_MESSAGE_MAX_COUNT 50
/** /**
* Sum of CannedMessageModuleConfig part sizes. * Sum of CannedMessageModuleConfig part sizes.
@ -64,7 +70,7 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
protected: protected:
virtual int32_t runOnce() override; virtual int32_t runOnce() override;
void sendText(NodeNum dest, const char *message, bool wantReplies); void sendText(NodeNum dest, ChannelIndex channel, const char *message, bool wantReplies);
int splitConfiguredMessages(); int splitConfiguredMessages();
int getNextIndex(); int getNextIndex();
@ -94,8 +100,11 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
char payload = 0x00; char payload = 0x00;
unsigned int cursor = 0; unsigned int cursor = 0;
String freetext = ""; // Text Buffer for Freetext Editor String freetext = ""; // Text Buffer for Freetext Editor
bool destSelect = false; // Freetext Editor Mode
NodeNum dest = NODENUM_BROADCAST; NodeNum dest = NODENUM_BROADCAST;
ChannelIndex channel = 0;
cannedMessageDestinationType destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
uint8_t numChannels = 0;
ChannelIndex indexChannels[MAX_NUM_CHANNELS] = {0};
NodeNum incoming = NODENUM_BROADCAST; NodeNum incoming = NODENUM_BROADCAST;
bool ack = false; // True means ACK, false means NAK (error_reason != NONE) bool ack = false; // True means ACK, false means NAK (error_reason != NONE)