mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-14 22:07:25 +00:00
Compare commits
6 Commits
master
...
BaseUI_Aut
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36f9cf1f68 | ||
|
|
ba2564eb32 | ||
|
|
8592b6eb82 | ||
|
|
5589d198a4 | ||
|
|
dfb8e21101 | ||
|
|
1c7ede6be7 |
@@ -13,6 +13,11 @@
|
|||||||
#define MESSAGE_TEXT_POOL_SIZE (MAX_MESSAGES_SAVED * MAX_MESSAGE_SIZE)
|
#define MESSAGE_TEXT_POOL_SIZE (MAX_MESSAGES_SAVED * MAX_MESSAGE_SIZE)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Default autosave interval 2 hours, override per device later with -DMESSAGE_AUTOSAVE_INTERVAL_SEC=300 (etc)
|
||||||
|
#ifndef MESSAGE_AUTOSAVE_INTERVAL_SEC
|
||||||
|
#define MESSAGE_AUTOSAVE_INTERVAL_SEC (2 * 60 * 60)
|
||||||
|
#endif
|
||||||
|
|
||||||
// Global message text pool and state
|
// Global message text pool and state
|
||||||
static char *g_messagePool = nullptr;
|
static char *g_messagePool = nullptr;
|
||||||
static size_t g_poolWritePos = 0;
|
static size_t g_poolWritePos = 0;
|
||||||
@@ -102,6 +107,60 @@ void MessageStore::addLiveMessage(const StoredMessage &msg)
|
|||||||
pushWithLimit(liveMessages, msg);
|
pushWithLimit(liveMessages, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_MESSAGE_PERSISTENCE
|
||||||
|
static bool g_messageStoreHasUnsavedChanges = false;
|
||||||
|
static uint32_t g_lastAutoSaveMs = 0; // last time we actually saved
|
||||||
|
|
||||||
|
static inline uint32_t autosaveIntervalMs()
|
||||||
|
{
|
||||||
|
uint32_t sec = (uint32_t)MESSAGE_AUTOSAVE_INTERVAL_SEC;
|
||||||
|
if (sec < 60)
|
||||||
|
sec = 60;
|
||||||
|
return sec * 1000UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool reachedMs(uint32_t now, uint32_t target)
|
||||||
|
{
|
||||||
|
return (int32_t)(now - target) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark new messages in RAM that need to be saved later
|
||||||
|
static inline void markMessageStoreUnsaved()
|
||||||
|
{
|
||||||
|
g_messageStoreHasUnsavedChanges = true;
|
||||||
|
|
||||||
|
if (g_lastAutoSaveMs == 0) {
|
||||||
|
g_lastAutoSaveMs = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called periodically from the main loop in main.cpp
|
||||||
|
static inline void autosaveTick(MessageStore *store)
|
||||||
|
{
|
||||||
|
if (!store)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t now = millis();
|
||||||
|
|
||||||
|
if (g_lastAutoSaveMs == 0) {
|
||||||
|
g_lastAutoSaveMs = now;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reachedMs(now, g_lastAutoSaveMs + autosaveIntervalMs()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Autosave interval reached, only save if there are unsaved messages.
|
||||||
|
if (g_messageStoreHasUnsavedChanges) {
|
||||||
|
LOG_INFO("Autosaving MessageStore to flash");
|
||||||
|
store->saveToFlash();
|
||||||
|
} else {
|
||||||
|
LOG_INFO("Autosave skipped, no changes to save");
|
||||||
|
g_lastAutoSaveMs = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Add from incoming/outgoing packet
|
// Add from incoming/outgoing packet
|
||||||
const StoredMessage &MessageStore::addFromPacket(const meshtastic_MeshPacket &packet)
|
const StoredMessage &MessageStore::addFromPacket(const meshtastic_MeshPacket &packet)
|
||||||
{
|
{
|
||||||
@@ -131,6 +190,11 @@ const StoredMessage &MessageStore::addFromPacket(const meshtastic_MeshPacket &pa
|
|||||||
}
|
}
|
||||||
|
|
||||||
addLiveMessage(sm);
|
addLiveMessage(sm);
|
||||||
|
|
||||||
|
#if ENABLE_MESSAGE_PERSISTENCE
|
||||||
|
markMessageStoreUnsaved();
|
||||||
|
#endif
|
||||||
|
|
||||||
return liveMessages.back();
|
return liveMessages.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,6 +219,10 @@ void MessageStore::addFromString(uint32_t sender, uint8_t channelIndex, const st
|
|||||||
sm.ackStatus = AckStatus::NONE;
|
sm.ackStatus = AckStatus::NONE;
|
||||||
|
|
||||||
addLiveMessage(sm);
|
addLiveMessage(sm);
|
||||||
|
|
||||||
|
#if ENABLE_MESSAGE_PERSISTENCE
|
||||||
|
markMessageStoreUnsaved();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_MESSAGE_PERSISTENCE
|
#if ENABLE_MESSAGE_PERSISTENCE
|
||||||
@@ -239,6 +307,10 @@ void MessageStore::saveToFlash()
|
|||||||
|
|
||||||
f.close();
|
f.close();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Reset autosave state after any save
|
||||||
|
g_messageStoreHasUnsavedChanges = false;
|
||||||
|
g_lastAutoSaveMs = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageStore::loadFromFlash()
|
void MessageStore::loadFromFlash()
|
||||||
@@ -270,6 +342,9 @@ void MessageStore::loadFromFlash()
|
|||||||
|
|
||||||
f.close();
|
f.close();
|
||||||
#endif
|
#endif
|
||||||
|
// Loading messages does not trigger an autosave
|
||||||
|
g_messageStoreHasUnsavedChanges = false;
|
||||||
|
g_lastAutoSaveMs = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@@ -290,6 +365,11 @@ void MessageStore::clearAllMessages()
|
|||||||
f.write(&count, 1); // write "0 messages"
|
f.write(&count, 1); // write "0 messages"
|
||||||
f.close();
|
f.close();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENABLE_MESSAGE_PERSISTENCE
|
||||||
|
g_messageStoreHasUnsavedChanges = false;
|
||||||
|
g_lastAutoSaveMs = millis();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal helper: erase first or last message matching a predicate
|
// Internal helper: erase first or last message matching a predicate
|
||||||
@@ -421,6 +501,14 @@ uint16_t MessageStore::storeText(const char *src, size_t len)
|
|||||||
return storeTextInPool(src, len);
|
return storeTextInPool(src, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_MESSAGE_PERSISTENCE
|
||||||
|
void messageStoreAutosaveTick()
|
||||||
|
{
|
||||||
|
// Called from the main loop to check autosave timing
|
||||||
|
autosaveTick(&messageStore);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Global definition
|
// Global definition
|
||||||
MessageStore messageStore("default");
|
MessageStore messageStore("default");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -125,6 +125,11 @@ class MessageStore
|
|||||||
std::string filename; // Flash filename for persistence
|
std::string filename; // Flash filename for persistence
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if ENABLE_MESSAGE_PERSISTENCE
|
||||||
|
// Called periodically from main loop to trigger time based autosave
|
||||||
|
void messageStoreAutosaveTick();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Global instance (defined in MessageStore.cpp)
|
// Global instance (defined in MessageStore.cpp)
|
||||||
extern MessageStore messageStore;
|
extern MessageStore messageStore;
|
||||||
|
|
||||||
|
|||||||
@@ -449,7 +449,7 @@ void menuHandler::clockMenu()
|
|||||||
}
|
}
|
||||||
void menuHandler::messageResponseMenu()
|
void menuHandler::messageResponseMenu()
|
||||||
{
|
{
|
||||||
enum optionsNumbers { Back = 0, ViewMode, DeleteAll, DeleteOldest, ReplyMenu, MuteChannel, Aloud, enumEnd };
|
enum optionsNumbers { Back = 0, ViewMode, DeleteMenu, ReplyMenu, MuteChannel, Aloud, enumEnd };
|
||||||
|
|
||||||
static const char *optionsArray[enumEnd];
|
static const char *optionsArray[enumEnd];
|
||||||
static int optionsEnumArray[enumEnd];
|
static int optionsEnumArray[enumEnd];
|
||||||
@@ -479,7 +479,7 @@ void menuHandler::messageResponseMenu()
|
|||||||
|
|
||||||
// Delete submenu
|
// Delete submenu
|
||||||
optionsArray[options] = "Delete";
|
optionsArray[options] = "Delete";
|
||||||
optionsEnumArray[options++] = 900;
|
optionsEnumArray[options++] = DeleteMenu;
|
||||||
|
|
||||||
#ifdef HAS_I2S
|
#ifdef HAS_I2S
|
||||||
optionsArray[options] = "Read Aloud";
|
optionsArray[options] = "Read Aloud";
|
||||||
@@ -520,34 +520,10 @@ void menuHandler::messageResponseMenu()
|
|||||||
nodeDB->saveToDisk();
|
nodeDB->saveToDisk();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete submenu
|
} else if (selected == DeleteMenu) {
|
||||||
} else if (selected == 900) {
|
|
||||||
menuHandler::menuQueue = menuHandler::delete_messages_menu;
|
menuHandler::menuQueue = menuHandler::delete_messages_menu;
|
||||||
screen->runNow();
|
screen->runNow();
|
||||||
|
|
||||||
// Delete oldest FIRST (only change)
|
|
||||||
} else if (selected == DeleteOldest) {
|
|
||||||
auto mode = graphics::MessageRenderer::getThreadMode();
|
|
||||||
int ch = graphics::MessageRenderer::getThreadChannel();
|
|
||||||
uint32_t peer = graphics::MessageRenderer::getThreadPeer();
|
|
||||||
|
|
||||||
if (mode == graphics::MessageRenderer::ThreadMode::ALL) {
|
|
||||||
// Global oldest
|
|
||||||
messageStore.deleteOldestMessage();
|
|
||||||
} else if (mode == graphics::MessageRenderer::ThreadMode::CHANNEL) {
|
|
||||||
// Oldest in current channel
|
|
||||||
messageStore.deleteOldestMessageInChannel(ch);
|
|
||||||
} else if (mode == graphics::MessageRenderer::ThreadMode::DIRECT) {
|
|
||||||
// Oldest in current DM
|
|
||||||
messageStore.deleteOldestMessageWithPeer(peer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete all messages
|
|
||||||
} else if (selected == DeleteAll) {
|
|
||||||
messageStore.clearAllMessages();
|
|
||||||
graphics::MessageRenderer::clearThreadRegistries();
|
|
||||||
graphics::MessageRenderer::clearMessageCache();
|
|
||||||
|
|
||||||
#ifdef HAS_I2S
|
#ifdef HAS_I2S
|
||||||
} else if (selected == Aloud) {
|
} else if (selected == Aloud) {
|
||||||
const meshtastic_MeshPacket &mp = devicestate.rx_text_message;
|
const meshtastic_MeshPacket &mp = devicestate.rx_text_message;
|
||||||
@@ -716,7 +692,6 @@ void menuHandler::deleteMessagesMenu()
|
|||||||
} else if (mode == graphics::MessageRenderer::ThreadMode::DIRECT) {
|
} else if (mode == graphics::MessageRenderer::ThreadMode::DIRECT) {
|
||||||
messageStore.deleteOldestMessageWithPeer(peer);
|
messageStore.deleteOldestMessageWithPeer(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -729,7 +704,6 @@ void menuHandler::deleteMessagesMenu()
|
|||||||
} else if (mode == graphics::MessageRenderer::ThreadMode::DIRECT) {
|
} else if (mode == graphics::MessageRenderer::ThreadMode::DIRECT) {
|
||||||
messageStore.deleteAllMessagesWithPeer(peer);
|
messageStore.deleteAllMessagesWithPeer(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -38,6 +38,9 @@
|
|||||||
#include "target_specific.h"
|
#include "target_specific.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#if HAS_SCREEN
|
||||||
|
#include "MessageStore.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ELECROW_ThinkNode_M5
|
#ifdef ELECROW_ThinkNode_M5
|
||||||
PCA9557 io(0x18, &Wire);
|
PCA9557 io(0x18, &Wire);
|
||||||
@@ -1652,6 +1655,9 @@ void loop()
|
|||||||
if (dispdev)
|
if (dispdev)
|
||||||
static_cast<TFTDisplay *>(dispdev)->sdlLoop();
|
static_cast<TFTDisplay *>(dispdev)->sdlLoop();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#if HAS_SCREEN && ENABLE_MESSAGE_PERSISTENCE
|
||||||
|
messageStoreAutosaveTick();
|
||||||
#endif
|
#endif
|
||||||
long delayMsec = mainController.runOrDelay();
|
long delayMsec = mainController.runOrDelay();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user