mirror of
https://github.com/meshtastic/firmware.git
synced 2025-02-26 22:33:24 +00:00
Merge branch 'master' into tft-gui-work
This commit is contained in:
commit
5c8fd379a4
@ -25,13 +25,9 @@ pio run --environment $1 # -v
|
||||
SRCELF=.pio/build/$1/firmware.elf
|
||||
cp $SRCELF $OUTDIR/$basename.elf
|
||||
|
||||
if (echo $1 | grep -q "wio-sdk-wm1110"); then
|
||||
echo "Skipping dfu file"
|
||||
else
|
||||
echo "Generating NRF52 dfu file"
|
||||
DFUPKG=.pio/build/$1/firmware.zip
|
||||
cp $DFUPKG $OUTDIR/$basename-ota.zip
|
||||
fi
|
||||
echo "Generating NRF52 dfu file"
|
||||
DFUPKG=.pio/build/$1/firmware.zip
|
||||
cp $DFUPKG $OUTDIR/$basename-ota.zip
|
||||
|
||||
echo "Generating NRF52 uf2 file"
|
||||
SRCHEX=.pio/build/$1/firmware.hex
|
||||
|
@ -41,6 +41,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "mesh/Channels.h"
|
||||
#include "mesh/generated/meshtastic/deviceonly.pb.h"
|
||||
#include "meshUtils.h"
|
||||
#include "modules/AdminModule.h"
|
||||
#include "modules/ExternalNotificationModule.h"
|
||||
#include "modules/TextMessageModule.h"
|
||||
#include "sleep.h"
|
||||
@ -1725,6 +1726,7 @@ void Screen::setup()
|
||||
powerStatusObserver.observe(&powerStatus->onNewStatus);
|
||||
gpsStatusObserver.observe(&gpsStatus->onNewStatus);
|
||||
nodeStatusObserver.observe(&nodeStatus->onNewStatus);
|
||||
adminMessageObserver.observe(adminModule);
|
||||
if (textMessageModule)
|
||||
textMessageObserver.observe(textMessageModule);
|
||||
if (inputBroker)
|
||||
@ -1953,9 +1955,6 @@ void Screen::setWelcomeFrames()
|
||||
/// Determine which screensaver frame to use, then set the FrameCallback
|
||||
void Screen::setScreensaverFrames(FrameCallback einkScreensaver)
|
||||
{
|
||||
// Remember current frame, restore position at power-on
|
||||
uint8_t frameNumber = ui->getUiState()->currentFrame;
|
||||
|
||||
// Retain specified frame / overlay callback beyond scope of this method
|
||||
static FrameCallback screensaverFrame;
|
||||
static OverlayCallback screensaverOverlay;
|
||||
@ -1993,9 +1992,8 @@ void Screen::setScreensaverFrames(FrameCallback einkScreensaver)
|
||||
#endif
|
||||
|
||||
// Prepare now for next frame, shown when display wakes
|
||||
ui->setOverlays(NULL, 0); // Clear overlay
|
||||
setFrames(); // Return to normal display updates
|
||||
ui->switchToFrame(frameNumber); // Attempt to return to same frame after power-on
|
||||
ui->setOverlays(NULL, 0); // Clear overlay
|
||||
setFrames(FOCUS_PRESERVE); // Return to normal display updates, showing same frame as before screensaver, ideally
|
||||
|
||||
// Pick a refresh method, for when display wakes
|
||||
#ifdef EINK_HASQUIRK_GHOSTING
|
||||
@ -2006,9 +2004,13 @@ void Screen::setScreensaverFrames(FrameCallback einkScreensaver)
|
||||
}
|
||||
#endif
|
||||
|
||||
// restore our regular frame list
|
||||
void Screen::setFrames()
|
||||
// Regenerate the normal set of frames, focusing a specific frame if requested
|
||||
// Called when a frame should be added / removed, or custom frames should be cleared
|
||||
void Screen::setFrames(FrameFocus focus)
|
||||
{
|
||||
uint8_t originalPosition = ui->getUiState()->currentFrame;
|
||||
FramesetInfo fsi; // Location of specific frames, for applying focus parameter
|
||||
|
||||
LOG_DEBUG("showing standard frames\n");
|
||||
showingNormalScreen = true;
|
||||
|
||||
@ -2042,20 +2044,33 @@ void Screen::setFrames()
|
||||
// is the same offset into the moduleFrames vector
|
||||
// so that we can invoke the module's callback
|
||||
for (auto i = moduleFrames.begin(); i != moduleFrames.end(); ++i) {
|
||||
normalFrames[numframes++] = drawModuleFrame;
|
||||
// Draw the module frame, using the hack described above
|
||||
normalFrames[numframes] = drawModuleFrame;
|
||||
|
||||
// Check if the module being drawn has requested focus
|
||||
// We will honor this request later, if setFrames was triggered by a UIFrameEvent
|
||||
MeshModule *m = *i;
|
||||
if (m->isRequestingFocus())
|
||||
fsi.positions.focusedModule = numframes;
|
||||
|
||||
numframes++;
|
||||
}
|
||||
|
||||
LOG_DEBUG("Added modules. numframes: %d\n", numframes);
|
||||
|
||||
// If we have a critical fault, show it first
|
||||
if (error_code)
|
||||
fsi.positions.fault = numframes;
|
||||
if (error_code) {
|
||||
normalFrames[numframes++] = drawCriticalFaultFrame;
|
||||
focus = FOCUS_FAULT; // Change our "focus" parameter, to ensure we show the fault frame
|
||||
}
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
normalFrames[numframes++] = screen->digitalWatchFace ? &Screen::drawDigitalClockFrame : &Screen::drawAnalogClockFrame;
|
||||
#endif
|
||||
|
||||
// If we have a text message - show it next, unless it's a phone message and we aren't using any special modules
|
||||
fsi.positions.textMessage = numframes;
|
||||
if (devicestate.has_rx_text_message && shouldDrawMessage(&devicestate.rx_text_message)) {
|
||||
normalFrames[numframes++] = drawTextMessageFrame;
|
||||
}
|
||||
@ -2070,11 +2085,14 @@ void Screen::setFrames()
|
||||
//
|
||||
// Since frames are basic function pointers, we have to use a helper to
|
||||
// call a method on debugInfo object.
|
||||
fsi.positions.log = numframes;
|
||||
normalFrames[numframes++] = &Screen::drawDebugInfoTrampoline;
|
||||
|
||||
// call a method on debugInfoScreen object (for more details)
|
||||
fsi.positions.settings = numframes;
|
||||
normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline;
|
||||
|
||||
fsi.positions.wifi = numframes;
|
||||
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
||||
if (isWifiAvailable()) {
|
||||
// call a method on debugInfoScreen object (for more details)
|
||||
@ -2082,6 +2100,7 @@ void Screen::setFrames()
|
||||
}
|
||||
#endif
|
||||
|
||||
fsi.frameCount = numframes; // Total framecount is used to apply FOCUS_PRESERVE
|
||||
LOG_DEBUG("Finished building frames. numframes: %d\n", numframes);
|
||||
|
||||
ui->setFrames(normalFrames, numframes);
|
||||
@ -2095,6 +2114,55 @@ void Screen::setFrames()
|
||||
prevFrame = -1; // Force drawNodeInfo to pick a new node (because our list
|
||||
// just changed)
|
||||
|
||||
// Focus on a specific frame, in the frame set we just created
|
||||
switch (focus) {
|
||||
case FOCUS_DEFAULT:
|
||||
ui->switchToFrame(0); // First frame
|
||||
break;
|
||||
case FOCUS_FAULT:
|
||||
ui->switchToFrame(fsi.positions.fault);
|
||||
break;
|
||||
case FOCUS_TEXTMESSAGE:
|
||||
ui->switchToFrame(fsi.positions.textMessage);
|
||||
break;
|
||||
case FOCUS_MODULE:
|
||||
// Whichever frame was marked by MeshModule::requestFocus(), if any
|
||||
// If no module requested focus, will show the first frame instead
|
||||
ui->switchToFrame(fsi.positions.focusedModule);
|
||||
break;
|
||||
|
||||
case FOCUS_PRESERVE:
|
||||
// If we can identify which type of frame "originalPosition" was, can move directly to it in the new frameset
|
||||
FramesetInfo &oldFsi = this->framesetInfo;
|
||||
if (originalPosition == oldFsi.positions.log)
|
||||
ui->switchToFrame(fsi.positions.log);
|
||||
else if (originalPosition == oldFsi.positions.settings)
|
||||
ui->switchToFrame(fsi.positions.settings);
|
||||
else if (originalPosition == oldFsi.positions.wifi)
|
||||
ui->switchToFrame(fsi.positions.wifi);
|
||||
|
||||
// If frame count has decreased
|
||||
else if (fsi.frameCount < oldFsi.frameCount) {
|
||||
uint8_t numDropped = oldFsi.frameCount - fsi.frameCount;
|
||||
// Move n frames backwards
|
||||
if (numDropped <= originalPosition)
|
||||
ui->switchToFrame(originalPosition - numDropped);
|
||||
// Unless that would put us "out of bounds" (< 0)
|
||||
else
|
||||
ui->switchToFrame(0);
|
||||
}
|
||||
|
||||
// If we're not sure exactly which frame we were on, at least return to the same frame number
|
||||
// (node frames; module frames)
|
||||
else
|
||||
ui->switchToFrame(originalPosition);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Store the info about this frameset, for future setFrames calls
|
||||
this->framesetInfo = fsi;
|
||||
|
||||
setFastFramerate(); // Draw ASAP
|
||||
}
|
||||
|
||||
@ -2549,7 +2617,7 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg)
|
||||
switch (arg->getStatusType()) {
|
||||
case STATUS_TYPE_NODE:
|
||||
if (showingNormalScreen && nodeStatus->getLastNumTotal() != nodeStatus->getNumTotal()) {
|
||||
setFrames(); // Regen the list of screens
|
||||
setFrames(FOCUS_PRESERVE); // Regen the list of screen frames (returning to same frame, if possible)
|
||||
}
|
||||
nodeDB->updateGUI = false;
|
||||
break;
|
||||
@ -2561,23 +2629,33 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg)
|
||||
int Screen::handleTextMessage(const meshtastic_MeshPacket *packet)
|
||||
{
|
||||
if (showingNormalScreen) {
|
||||
setFrames(); // Regen the list of screens (will show new text message)
|
||||
// Outgoing message
|
||||
if (packet->from == 0)
|
||||
setFrames(FOCUS_PRESERVE); // Return to same frame (quietly hiding the rx text message frame)
|
||||
|
||||
// Incoming message
|
||||
else
|
||||
setFrames(FOCUS_TEXTMESSAGE); // Focus on the new message
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Triggered by MeshModules
|
||||
int Screen::handleUIFrameEvent(const UIFrameEvent *event)
|
||||
{
|
||||
if (showingNormalScreen) {
|
||||
if (event->frameChanged) {
|
||||
setFrames(); // Regen the list of screens (will show new text message)
|
||||
} else if (event->needRedraw) {
|
||||
// Regenerate the frameset, potentially honoring a module's internal requestFocus() call
|
||||
if (event->action == UIFrameEvent::Action::REGENERATE_FRAMESET)
|
||||
setFrames(FOCUS_MODULE);
|
||||
|
||||
// Regenerate the frameset, while attempting to maintain focus on the current frame
|
||||
else if (event->action == UIFrameEvent::Action::REGENERATE_FRAMESET_BACKGROUND)
|
||||
setFrames(FOCUS_PRESERVE);
|
||||
|
||||
// Don't regenerate the frameset, just re-draw whatever is on screen ASAP
|
||||
else if (event->action == UIFrameEvent::Action::REDRAW_ONLY)
|
||||
setFastFramerate();
|
||||
// TODO: We might also want switch to corresponding frame,
|
||||
// but we don't know the exact frame number.
|
||||
// ui->switchToFrame(0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -2612,6 +2690,24 @@ int Screen::handleInputEvent(const InputEvent *event)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg)
|
||||
{
|
||||
// Note: only selected admin messages notify this observer
|
||||
// If you wish to handle a new type of message, you should modify AdminModule.cpp first
|
||||
|
||||
switch (arg->which_payload_variant) {
|
||||
// Node removed manually (i.e. via app)
|
||||
case meshtastic_AdminMessage_remove_by_nodenum_tag:
|
||||
setFrames(FOCUS_PRESERVE);
|
||||
break;
|
||||
|
||||
// Default no-op, in case the admin message observable gets used by other classes in future
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace graphics
|
||||
#else
|
||||
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
|
||||
|
@ -173,9 +173,11 @@ class Screen : public concurrency::OSThread
|
||||
CallbackObserver<Screen, const meshtastic_MeshPacket *> textMessageObserver =
|
||||
CallbackObserver<Screen, const meshtastic_MeshPacket *>(this, &Screen::handleTextMessage);
|
||||
CallbackObserver<Screen, const UIFrameEvent *> uiFrameEventObserver =
|
||||
CallbackObserver<Screen, const UIFrameEvent *>(this, &Screen::handleUIFrameEvent);
|
||||
CallbackObserver<Screen, const UIFrameEvent *>(this, &Screen::handleUIFrameEvent); // Sent by Mesh Modules
|
||||
CallbackObserver<Screen, const InputEvent *> inputObserver =
|
||||
CallbackObserver<Screen, const InputEvent *>(this, &Screen::handleInputEvent);
|
||||
CallbackObserver<Screen, const meshtastic_AdminMessage *> adminMessageObserver =
|
||||
CallbackObserver<Screen, const meshtastic_AdminMessage *>(this, &Screen::handleAdminMessage);
|
||||
|
||||
public:
|
||||
explicit Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY);
|
||||
@ -394,6 +396,7 @@ class Screen : public concurrency::OSThread
|
||||
int handleTextMessage(const meshtastic_MeshPacket *arg);
|
||||
int handleUIFrameEvent(const UIFrameEvent *arg);
|
||||
int handleInputEvent(const InputEvent *arg);
|
||||
int handleAdminMessage(const meshtastic_AdminMessage *arg);
|
||||
|
||||
/// Used to force (super slow) eink displays to draw critical frames
|
||||
void forceDisplay(bool forceUiUpdate = false);
|
||||
@ -450,8 +453,34 @@ class Screen : public concurrency::OSThread
|
||||
void handleShowPrevFrame();
|
||||
void handlePrint(const char *text);
|
||||
void handleStartFirmwareUpdateScreen();
|
||||
/// Rebuilds our list of frames (screens) to default ones.
|
||||
void setFrames();
|
||||
|
||||
// Info collected by setFrames method.
|
||||
// Index location of specific frames. Used to apply the FrameFocus parameter of setFrames
|
||||
struct FramesetInfo {
|
||||
struct FramePositions {
|
||||
uint8_t fault = 0;
|
||||
uint8_t textMessage = 0;
|
||||
uint8_t focusedModule = 0;
|
||||
uint8_t log = 0;
|
||||
uint8_t settings = 0;
|
||||
uint8_t wifi = 0;
|
||||
} positions;
|
||||
|
||||
uint8_t frameCount = 0;
|
||||
} framesetInfo;
|
||||
|
||||
// Which frame we want to be displayed, after we regen the frameset by calling setFrames
|
||||
enum FrameFocus : uint8_t {
|
||||
FOCUS_DEFAULT, // No specific frame
|
||||
FOCUS_PRESERVE, // Return to the previous frame
|
||||
FOCUS_FAULT,
|
||||
FOCUS_TEXTMESSAGE,
|
||||
FOCUS_MODULE, // Note: target module should call requestFocus(), otherwise no info about which module to focus
|
||||
};
|
||||
|
||||
// Regenerate the normal set of frames, focusing a specific frame if requested
|
||||
// Call when a frame should be added / removed, or custom frames should be cleared
|
||||
void setFrames(FrameFocus focus = FOCUS_DEFAULT);
|
||||
|
||||
/// Try to start drawing ASAP
|
||||
void setFastFramerate();
|
||||
|
@ -5,6 +5,7 @@
|
||||
#define ONE_MINUTE_MS 60 * 1000
|
||||
|
||||
#define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60)
|
||||
#define default_telemetry_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 30 * 60)
|
||||
#define default_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 15 * 60)
|
||||
#define default_wait_bluetooth_secs IF_ROUTER(1, 60)
|
||||
#define default_sds_secs IF_ROUTER(ONE_DAY, UINT32_MAX) // Default to forever super deep sleep
|
||||
|
@ -284,4 +284,17 @@ AdminMessageHandleResult MeshModule::handleAdminMessageForAllModules(const mesht
|
||||
}
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
}
|
||||
|
||||
#if HAS_SCREEN
|
||||
// Would our module like its frame to be focused after Screen::setFrames has regenerated the list of frames?
|
||||
// Only considered if setFrames is triggered by a UIFrameEvent
|
||||
bool MeshModule::isRequestingFocus()
|
||||
{
|
||||
if (_requestingFocus) {
|
||||
_requestingFocus = false; // Consume the request
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
#endif
|
@ -35,10 +35,16 @@ enum class AdminMessageHandleResult {
|
||||
/*
|
||||
* This struct is used by Screen to figure out whether screen frame should be updated.
|
||||
*/
|
||||
typedef struct _UIFrameEvent {
|
||||
bool frameChanged;
|
||||
bool needRedraw;
|
||||
} UIFrameEvent;
|
||||
struct UIFrameEvent {
|
||||
// What do we actually want to happen?
|
||||
enum Action {
|
||||
REDRAW_ONLY, // Don't change which frames are show, just redraw, asap
|
||||
REGENERATE_FRAMESET, // Regenerate (change? add? remove?) screen frames, honoring requestFocus()
|
||||
REGENERATE_FRAMESET_BACKGROUND, // Regenerate screen frames, attempting to remain on the same frame throughout
|
||||
} action = REDRAW_ONLY;
|
||||
|
||||
// We might want to pass additional data inside this struct at some point
|
||||
};
|
||||
|
||||
/** A baseclass for any mesh "module".
|
||||
*
|
||||
@ -73,6 +79,7 @@ class MeshModule
|
||||
meshtastic_AdminMessage *response);
|
||||
#if HAS_SCREEN
|
||||
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { return; }
|
||||
virtual bool isRequestingFocus(); // Checked by screen, when regenerating frameset
|
||||
#endif
|
||||
protected:
|
||||
const char *name;
|
||||
@ -176,6 +183,19 @@ class MeshModule
|
||||
return AdminMessageHandleResult::NOT_HANDLED;
|
||||
};
|
||||
|
||||
#if HAS_SCREEN
|
||||
/** Request that our module's screen frame be focused when Screen::setFrames runs
|
||||
* Only considered if Screen::setFrames is triggered via a UIFrameEvent
|
||||
*
|
||||
* Having this as a separate call, instead of part of the UIFrameEvent, allows the module to delay decision
|
||||
* until drawFrame() is called. This required less restructuring.
|
||||
*/
|
||||
bool _requestingFocus = false;
|
||||
void requestFocus() { _requestingFocus = true; }
|
||||
#else
|
||||
void requestFocus(){}; // No-op
|
||||
#endif
|
||||
|
||||
private:
|
||||
/**
|
||||
* If any of the current chain of modules has already sent a reply, it will be here. This is useful to allow
|
||||
|
@ -200,6 +200,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
case meshtastic_AdminMessage_remove_by_nodenum_tag: {
|
||||
LOG_INFO("Client is receiving a remove_nodenum command.\n");
|
||||
nodeDB->removeNodeByNum(r->remove_by_nodenum);
|
||||
this->notifyObservers(r); // Observed by screen
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_set_favorite_node_tag: {
|
||||
|
@ -7,7 +7,7 @@
|
||||
/**
|
||||
* Admin module for admin messages
|
||||
*/
|
||||
class AdminModule : public ProtobufModule<meshtastic_AdminMessage>
|
||||
class AdminModule : public ProtobufModule<meshtastic_AdminMessage>, public Observable<const meshtastic_AdminMessage *>
|
||||
{
|
||||
public:
|
||||
/** Constructor
|
||||
|
@ -148,8 +148,9 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
if (this->currentMessageIndex == 0) {
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_FREETEXT;
|
||||
|
||||
UIFrameEvent e = {false, true};
|
||||
e.frameChanged = true;
|
||||
requestFocus(); // Tell Screen::setFrames to move to our module's frame, next time it runs
|
||||
UIFrameEvent e;
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
|
||||
this->notifyObservers(&e);
|
||||
|
||||
return 0;
|
||||
@ -166,8 +167,8 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
}
|
||||
}
|
||||
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL)) {
|
||||
UIFrameEvent e = {false, true};
|
||||
e.frameChanged = true;
|
||||
UIFrameEvent e;
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
|
||||
this->currentMessageIndex = -1;
|
||||
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014)
|
||||
@ -353,6 +354,8 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
}
|
||||
|
||||
if (validEvent) {
|
||||
requestFocus(); // Tell Screen::setFrames to move to our module's frame, next time it runs
|
||||
|
||||
// Let runOnce to be called immediately.
|
||||
if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_SELECT) {
|
||||
setIntervalFromNow(0); // on fast keypresses, this isn't fast enough.
|
||||
@ -378,6 +381,11 @@ void CannedMessageModule::sendText(NodeNum dest, ChannelIndex channel, const cha
|
||||
p->decoded.payload.size++;
|
||||
}
|
||||
|
||||
// Only receive routing messages when expecting ACK for a canned message
|
||||
// Prevents the canned message module from regenerating the screen's frameset at unexpected times,
|
||||
// or raising a UIFrameEvent before another module has the chance
|
||||
this->waitingForAck = true;
|
||||
|
||||
LOG_INFO("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
|
||||
|
||||
service.sendToMesh(
|
||||
@ -393,13 +401,13 @@ int32_t CannedMessageModule::runOnce()
|
||||
return INT32_MAX;
|
||||
}
|
||||
// LOG_DEBUG("Check status\n");
|
||||
UIFrameEvent e = {false, true};
|
||||
UIFrameEvent e;
|
||||
if ((this->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) ||
|
||||
(this->runState == CANNED_MESSAGE_RUN_STATE_ACK_NACK_RECEIVED) || (this->runState == CANNED_MESSAGE_RUN_STATE_MESSAGE)) {
|
||||
// TODO: might have some feedback of sending state
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
temporaryMessage = "";
|
||||
e.frameChanged = true;
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
|
||||
this->currentMessageIndex = -1;
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
@ -412,7 +420,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
} else if (((this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT)) &&
|
||||
((millis() - this->lastTouchMillis) > INACTIVATE_AFTER_MS)) {
|
||||
// Reset module
|
||||
e.frameChanged = true;
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
|
||||
this->currentMessageIndex = -1;
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
@ -449,7 +457,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
}
|
||||
}
|
||||
e.frameChanged = true;
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
|
||||
this->currentMessageIndex = -1;
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
@ -463,7 +471,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
} else if ((this->runState != CANNED_MESSAGE_RUN_STATE_FREETEXT) && (this->currentMessageIndex == -1)) {
|
||||
this->currentMessageIndex = 0;
|
||||
LOG_DEBUG("First touch (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage());
|
||||
e.frameChanged = true;
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
|
||||
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_UP) {
|
||||
if (this->messagesCount > 0) {
|
||||
@ -567,7 +575,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
break;
|
||||
}
|
||||
if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
||||
e.frameChanged = true;
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
|
||||
switch (this->payload) { // code below all trigger the freetext window (where you type to send a message) or reset the
|
||||
// display back to the default window
|
||||
case 0x08: // backspace
|
||||
@ -706,8 +714,8 @@ int CannedMessageModule::getPrevIndex()
|
||||
void CannedMessageModule::showTemporaryMessage(const String &message)
|
||||
{
|
||||
temporaryMessage = message;
|
||||
UIFrameEvent e = {false, true};
|
||||
e.frameChanged = true;
|
||||
UIFrameEvent e;
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
|
||||
notifyObservers(&e);
|
||||
runState = CANNED_MESSAGE_RUN_STATE_MESSAGE;
|
||||
// run this loop again in 2 seconds, next iteration will clear the display
|
||||
@ -915,11 +923,13 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
char buffer[50];
|
||||
|
||||
if (temporaryMessage.length() != 0) {
|
||||
requestFocus(); // Tell Screen::setFrames to move to our module's frame
|
||||
LOG_DEBUG("Drawing temporary message: %s", temporaryMessage.c_str());
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
display->drawString(display->getWidth() / 2 + x, 0 + y + 12, temporaryMessage);
|
||||
} else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_ACK_NACK_RECEIVED) {
|
||||
requestFocus(); // Tell Screen::setFrames to move to our module's frame
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
String displayString;
|
||||
@ -941,6 +951,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
display->drawStringf(display->getWidth() / 2 + x, y + 130, buffer, rssiString, this->lastRxRssi);
|
||||
}
|
||||
} else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) {
|
||||
requestFocus(); // Tell Screen::setFrames to move to our module's frame
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
display->drawString(display->getWidth() / 2 + x, 0 + y + 12, "Sending...");
|
||||
@ -949,7 +960,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
display->setFont(FONT_SMALL);
|
||||
display->drawString(10 + x, 0 + y + FONT_HEIGHT_SMALL, "Canned Message\nModule disabled.");
|
||||
} else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
||||
|
||||
requestFocus(); // Tell Screen::setFrames to move to our module's frame
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
drawKeyboard(display, state, 0, 0);
|
||||
#else
|
||||
@ -1032,16 +1043,18 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
|
||||
ProcessMessage CannedMessageModule::handleReceived(const meshtastic_MeshPacket &mp)
|
||||
{
|
||||
if (mp.decoded.portnum == meshtastic_PortNum_ROUTING_APP) {
|
||||
if (mp.decoded.portnum == meshtastic_PortNum_ROUTING_APP && waitingForAck) {
|
||||
// look for a request_id
|
||||
if (mp.decoded.request_id != 0) {
|
||||
UIFrameEvent e = {false, true};
|
||||
e.frameChanged = true;
|
||||
UIFrameEvent e;
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
|
||||
requestFocus(); // Tell Screen::setFrames that our module's frame should be shown, even if not "first" in the frameset
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_ACK_NACK_RECEIVED;
|
||||
this->incoming = service.getNodenumFromRequestId(mp.decoded.request_id);
|
||||
meshtastic_Routing decoded = meshtastic_Routing_init_default;
|
||||
pb_decode_from_bytes(mp.decoded.payload.bytes, mp.decoded.payload.size, meshtastic_Routing_fields, &decoded);
|
||||
this->ack = decoded.error_reason == meshtastic_Routing_Error_NONE;
|
||||
waitingForAck = false; // No longer want routing packets
|
||||
this->notifyObservers(&e);
|
||||
// run the next time 2 seconds later
|
||||
setIntervalFromNow(2000);
|
||||
|
@ -81,9 +81,8 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
|
||||
}
|
||||
|
||||
switch (p->decoded.portnum) {
|
||||
case meshtastic_PortNum_TEXT_MESSAGE_APP:
|
||||
case meshtastic_PortNum_ROUTING_APP:
|
||||
return true;
|
||||
return waitingForAck;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -142,7 +141,8 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
|
||||
uint8_t numChannels = 0;
|
||||
ChannelIndex indexChannels[MAX_NUM_CHANNELS] = {0};
|
||||
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)
|
||||
bool waitingForAck = false; // Are currently interested in routing packets?
|
||||
float lastRxSnr = 0;
|
||||
int32_t lastRxRssi = 0;
|
||||
|
||||
|
@ -47,7 +47,8 @@ int32_t AirQualityTelemetryModule::runOnce()
|
||||
|
||||
uint32_t now = millis();
|
||||
if (((lastSentToMesh == 0) ||
|
||||
((now - lastSentToMesh) >= Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.air_quality_interval))) &&
|
||||
((now - lastSentToMesh) >= Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.air_quality_interval,
|
||||
default_telemetry_broadcast_interval_secs))) &&
|
||||
airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
|
||||
airTime->isTxAllowedAirUtil()) {
|
||||
sendTelemetry();
|
||||
|
@ -17,7 +17,8 @@ int32_t DeviceTelemetryModule::runOnce()
|
||||
{
|
||||
refreshUptime();
|
||||
if (((lastSentToMesh == 0) ||
|
||||
((uptimeLastMs - lastSentToMesh) >= Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval))) &&
|
||||
((uptimeLastMs - lastSentToMesh) >= Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval,
|
||||
default_telemetry_broadcast_interval_secs))) &&
|
||||
airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
|
||||
airTime->isTxAllowedAirUtil() && config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER &&
|
||||
config.device.role != meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN) {
|
||||
|
@ -63,7 +63,8 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
{
|
||||
if (sleepOnNextExecution == true) {
|
||||
sleepOnNextExecution = false;
|
||||
uint32_t nightyNightMs = Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval);
|
||||
uint32_t nightyNightMs = Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval,
|
||||
default_telemetry_broadcast_interval_secs);
|
||||
LOG_DEBUG("Sleeping for %ims, then awaking to send metrics again.\n", nightyNightMs);
|
||||
doDeepSleep(nightyNightMs, true);
|
||||
}
|
||||
@ -144,7 +145,8 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
|
||||
uint32_t now = millis();
|
||||
if (((lastSentToMesh == 0) ||
|
||||
((now - lastSentToMesh) >= Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval))) &&
|
||||
((now - lastSentToMesh) >= Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval,
|
||||
default_telemetry_broadcast_interval_secs))) &&
|
||||
airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
|
||||
airTime->isTxAllowedAirUtil()) {
|
||||
sendTelemetry();
|
||||
|
@ -24,7 +24,8 @@ int32_t PowerTelemetryModule::runOnce()
|
||||
{
|
||||
if (sleepOnNextExecution == true) {
|
||||
sleepOnNextExecution = false;
|
||||
uint32_t nightyNightMs = Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.power_update_interval);
|
||||
uint32_t nightyNightMs = Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.power_update_interval,
|
||||
default_telemetry_broadcast_interval_secs);
|
||||
LOG_DEBUG("Sleeping for %ims, then awaking to send metrics again.\n", nightyNightMs);
|
||||
doDeepSleep(nightyNightMs, true);
|
||||
}
|
||||
@ -70,7 +71,8 @@ int32_t PowerTelemetryModule::runOnce()
|
||||
|
||||
uint32_t now = millis();
|
||||
if (((lastSentToMesh == 0) ||
|
||||
((now - lastSentToMesh) >= Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.power_update_interval))) &&
|
||||
((now - lastSentToMesh) >= Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.power_update_interval,
|
||||
default_telemetry_broadcast_interval_secs))) &&
|
||||
airTime->isTxAllowedAirUtil()) {
|
||||
sendTelemetry();
|
||||
lastSentToMesh = now;
|
||||
|
@ -16,15 +16,31 @@ ProcessMessage WaypointModule::handleReceived(const meshtastic_MeshPacket &mp)
|
||||
auto &p = mp.decoded;
|
||||
LOG_INFO("Received waypoint msg from=0x%0x, id=0x%x, msg=%.*s\n", mp.from, mp.id, p.payload.size, p.payload.bytes);
|
||||
#endif
|
||||
UIFrameEvent e = {true, true};
|
||||
// We only store/display messages destined for us.
|
||||
// Keep a copy of the most recent text message.
|
||||
devicestate.rx_waypoint = mp;
|
||||
devicestate.has_rx_waypoint = true;
|
||||
|
||||
powerFSM.trigger(EVENT_RECEIVED_MSG);
|
||||
|
||||
#if HAS_SCREEN
|
||||
|
||||
UIFrameEvent e;
|
||||
|
||||
// New or updated waypoint: focus on this frame next time Screen::setFrames runs
|
||||
if (shouldDraw()) {
|
||||
requestFocus();
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||
}
|
||||
|
||||
// Deleting an old waypoint: remove the frame quietly, don't change frame position if possible
|
||||
else
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET_BACKGROUND;
|
||||
|
||||
notifyObservers(&e);
|
||||
|
||||
#endif
|
||||
|
||||
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
|
||||
}
|
||||
|
||||
|
@ -190,13 +190,13 @@ int32_t AudioModule::runOnce()
|
||||
|
||||
firstTime = false;
|
||||
} else {
|
||||
UIFrameEvent e = {false, true};
|
||||
UIFrameEvent e;
|
||||
// Check if PTT is pressed. TODO hook that into Onebutton/Interrupt drive.
|
||||
if (digitalRead(moduleConfig.audio.ptt_pin ? moduleConfig.audio.ptt_pin : PTT_PIN) == HIGH) {
|
||||
if (radio_state == RadioState::rx) {
|
||||
LOG_INFO("PTT pressed, switching to TX\n");
|
||||
radio_state = RadioState::tx;
|
||||
e.frameChanged = true;
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
} else {
|
||||
@ -209,7 +209,7 @@ int32_t AudioModule::runOnce()
|
||||
}
|
||||
tx_encode_frame_index = sizeof(tx_header);
|
||||
radio_state = RadioState::rx;
|
||||
e.frameChanged = true;
|
||||
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ int32_t PaxcounterModule::runOnce()
|
||||
sendInfo(NODENUM_BROADCAST);
|
||||
}
|
||||
return Default::getConfiguredOrDefaultMs(moduleConfig.paxcounter.paxcounter_update_interval,
|
||||
default_broadcast_interval_secs);
|
||||
default_telemetry_broadcast_interval_secs);
|
||||
} else {
|
||||
return disable();
|
||||
}
|
||||
|
@ -286,5 +286,10 @@ void clearBonds()
|
||||
|
||||
void enterDfuMode()
|
||||
{
|
||||
// SDK kit does not have native USB like almost all other NRF52 boards
|
||||
#ifdef NRF_USE_SERIAL_DFU
|
||||
enterSerialDfu();
|
||||
#else
|
||||
enterUf2Dfu();
|
||||
#endif
|
||||
}
|
@ -20,7 +20,7 @@ debug_tool = jlink
|
||||
; No need to reflash if the binary hasn't changed
|
||||
debug_load_mode = modified
|
||||
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
|
||||
upload_protocol = jlink
|
||||
upload_protocol = nrfutil
|
||||
;upload_protocol = stlink
|
||||
; we prefer to stop in setup() because we are an 'ardiuno' app
|
||||
debug_init_break = tbreak setup
|
||||
|
@ -107,6 +107,8 @@ extern "C" {
|
||||
|
||||
#define LR1110_GNSS_ANT_PIN (32 + 5) // P1.05 37
|
||||
|
||||
#define NRF_USE_SERIAL_DFU
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user