mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-29 13:12:04 +00:00
Merge branch 'develop' into baseui_nodeactionsoverhaul
This commit is contained in:
@@ -13,6 +13,11 @@
|
||||
#define MESSAGE_TEXT_POOL_SIZE (MAX_MESSAGES_SAVED * MAX_MESSAGE_SIZE)
|
||||
#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
|
||||
static char *g_messagePool = nullptr;
|
||||
static size_t g_poolWritePos = 0;
|
||||
@@ -102,6 +107,60 @@ void MessageStore::addLiveMessage(const StoredMessage &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
|
||||
const StoredMessage &MessageStore::addFromPacket(const meshtastic_MeshPacket &packet)
|
||||
{
|
||||
@@ -131,6 +190,11 @@ const StoredMessage &MessageStore::addFromPacket(const meshtastic_MeshPacket &pa
|
||||
}
|
||||
|
||||
addLiveMessage(sm);
|
||||
|
||||
#if ENABLE_MESSAGE_PERSISTENCE
|
||||
markMessageStoreUnsaved();
|
||||
#endif
|
||||
|
||||
return liveMessages.back();
|
||||
}
|
||||
|
||||
@@ -155,6 +219,10 @@ void MessageStore::addFromString(uint32_t sender, uint8_t channelIndex, const st
|
||||
sm.ackStatus = AckStatus::NONE;
|
||||
|
||||
addLiveMessage(sm);
|
||||
|
||||
#if ENABLE_MESSAGE_PERSISTENCE
|
||||
markMessageStoreUnsaved();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_MESSAGE_PERSISTENCE
|
||||
@@ -239,6 +307,10 @@ void MessageStore::saveToFlash()
|
||||
|
||||
f.close();
|
||||
#endif
|
||||
|
||||
// Reset autosave state after any save
|
||||
g_messageStoreHasUnsavedChanges = false;
|
||||
g_lastAutoSaveMs = millis();
|
||||
}
|
||||
|
||||
void MessageStore::loadFromFlash()
|
||||
@@ -270,6 +342,9 @@ void MessageStore::loadFromFlash()
|
||||
|
||||
f.close();
|
||||
#endif
|
||||
// Loading messages does not trigger an autosave
|
||||
g_messageStoreHasUnsavedChanges = false;
|
||||
g_lastAutoSaveMs = millis();
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -290,6 +365,11 @@ void MessageStore::clearAllMessages()
|
||||
f.write(&count, 1); // write "0 messages"
|
||||
f.close();
|
||||
#endif
|
||||
|
||||
#if ENABLE_MESSAGE_PERSISTENCE
|
||||
g_messageStoreHasUnsavedChanges = false;
|
||||
g_lastAutoSaveMs = millis();
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
#if ENABLE_MESSAGE_PERSISTENCE
|
||||
void messageStoreAutosaveTick()
|
||||
{
|
||||
// Called from the main loop to check autosave timing
|
||||
autosaveTick(&messageStore);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Global definition
|
||||
MessageStore messageStore("default");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -125,6 +125,11 @@ class MessageStore
|
||||
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)
|
||||
extern MessageStore messageStore;
|
||||
|
||||
|
||||
@@ -450,7 +450,7 @@ void menuHandler::clockMenu()
|
||||
}
|
||||
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 int optionsEnumArray[enumEnd];
|
||||
@@ -480,7 +480,7 @@ void menuHandler::messageResponseMenu()
|
||||
|
||||
// Delete submenu
|
||||
optionsArray[options] = "Delete";
|
||||
optionsEnumArray[options++] = 900;
|
||||
optionsEnumArray[options++] = DeleteMenu;
|
||||
|
||||
#ifdef HAS_I2S
|
||||
optionsArray[options] = "Read Aloud";
|
||||
@@ -521,34 +521,10 @@ void menuHandler::messageResponseMenu()
|
||||
nodeDB->saveToDisk();
|
||||
}
|
||||
|
||||
// Delete submenu
|
||||
} else if (selected == 900) {
|
||||
} else if (selected == DeleteMenu) {
|
||||
menuHandler::menuQueue = menuHandler::delete_messages_menu;
|
||||
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
|
||||
} else if (selected == Aloud) {
|
||||
const meshtastic_MeshPacket &mp = devicestate.rx_text_message;
|
||||
@@ -717,7 +693,6 @@ void menuHandler::deleteMessagesMenu()
|
||||
} else if (mode == graphics::MessageRenderer::ThreadMode::DIRECT) {
|
||||
messageStore.deleteOldestMessageWithPeer(peer);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -730,7 +705,6 @@ void menuHandler::deleteMessagesMenu()
|
||||
} else if (mode == graphics::MessageRenderer::ThreadMode::DIRECT) {
|
||||
messageStore.deleteAllMessagesWithPeer(peer);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
#include "target_specific.h"
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#if HAS_SCREEN
|
||||
#include "MessageStore.h"
|
||||
#endif
|
||||
|
||||
#ifdef ELECROW_ThinkNode_M5
|
||||
PCA9557 io(0x18, &Wire);
|
||||
@@ -1652,6 +1655,9 @@ void loop()
|
||||
if (dispdev)
|
||||
static_cast<TFTDisplay *>(dispdev)->sdlLoop();
|
||||
}
|
||||
#endif
|
||||
#if HAS_SCREEN && ENABLE_MESSAGE_PERSISTENCE
|
||||
messageStoreAutosaveTick();
|
||||
#endif
|
||||
long delayMsec = mainController.runOrDelay();
|
||||
|
||||
|
||||
@@ -281,8 +281,6 @@ typedef struct _meshtastic_AdminMessage {
|
||||
meshtastic_SharedContact add_contact;
|
||||
/* Initiate or respond to a key verification request */
|
||||
meshtastic_KeyVerificationAdmin key_verification;
|
||||
/* Tell the node to reboot into OTA mode for firmware update via BLE or WiFi (ESP32 only for now) */
|
||||
meshtastic_OTAMode reboot_ota_mode;
|
||||
/* Tell the node to factory reset config everything; all device state and configuration will be returned to factory defaults and BLE bonds will be cleared. */
|
||||
int32_t factory_reset_device;
|
||||
/* Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot)
|
||||
@@ -341,7 +339,6 @@ extern "C" {
|
||||
#define meshtastic_AdminMessage_payload_variant_backup_preferences_ENUMTYPE meshtastic_AdminMessage_BackupLocation
|
||||
#define meshtastic_AdminMessage_payload_variant_restore_preferences_ENUMTYPE meshtastic_AdminMessage_BackupLocation
|
||||
#define meshtastic_AdminMessage_payload_variant_remove_backup_preferences_ENUMTYPE meshtastic_AdminMessage_BackupLocation
|
||||
#define meshtastic_AdminMessage_payload_variant_reboot_ota_mode_ENUMTYPE meshtastic_OTAMode
|
||||
|
||||
|
||||
#define meshtastic_AdminMessage_OTAEvent_reboot_ota_mode_ENUMTYPE meshtastic_OTAMode
|
||||
@@ -436,7 +433,6 @@ extern "C" {
|
||||
#define meshtastic_AdminMessage_commit_edit_settings_tag 65
|
||||
#define meshtastic_AdminMessage_add_contact_tag 66
|
||||
#define meshtastic_AdminMessage_key_verification_tag 67
|
||||
#define meshtastic_AdminMessage_reboot_ota_mode_tag 68
|
||||
#define meshtastic_AdminMessage_factory_reset_device_tag 94
|
||||
#define meshtastic_AdminMessage_reboot_ota_seconds_tag 95
|
||||
#define meshtastic_AdminMessage_exit_simulator_tag 96
|
||||
@@ -497,7 +493,6 @@ X(a, STATIC, ONEOF, BOOL, (payload_variant,begin_edit_settings,begin_ed
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,commit_edit_settings,commit_edit_settings), 65) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,add_contact,add_contact), 66) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification,key_verification), 67) \
|
||||
X(a, STATIC, ONEOF, UENUM, (payload_variant,reboot_ota_mode,reboot_ota_mode), 68) \
|
||||
X(a, STATIC, ONEOF, INT32, (payload_variant,factory_reset_device,factory_reset_device), 94) \
|
||||
X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_ota_seconds,reboot_ota_seconds), 95) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,exit_simulator,exit_simulator), 96) \
|
||||
|
||||
@@ -296,6 +296,8 @@ typedef enum _meshtastic_HardwareModel {
|
||||
meshtastic_HardwareModel_THINKNODE_M6 = 120,
|
||||
/* Elecrow Meshstick 1262 */
|
||||
meshtastic_HardwareModel_MESHSTICK_1262 = 121,
|
||||
/* LilyGo T-Beam 1W */
|
||||
meshtastic_HardwareModel_TBEAM_1_WATT = 122,
|
||||
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
|
||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
@@ -1366,10 +1368,6 @@ extern "C" {
|
||||
#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_MAX meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF
|
||||
#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_ARRAYSIZE ((meshtastic_StoreForwardPlusPlus_SFPP_message_type)(meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF+1))
|
||||
|
||||
#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN meshtastic_StoreForwardPlusPlus_SFPP_message_type_CANON_ANNOUNCE
|
||||
#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_MAX meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF
|
||||
#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_ARRAYSIZE ((meshtastic_StoreForwardPlusPlus_SFPP_message_type)(meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF+1))
|
||||
|
||||
#define _meshtastic_MeshPacket_Priority_MIN meshtastic_MeshPacket_Priority_UNSET
|
||||
#define _meshtastic_MeshPacket_Priority_MAX meshtastic_MeshPacket_Priority_MAX
|
||||
#define _meshtastic_MeshPacket_Priority_ARRAYSIZE ((meshtastic_MeshPacket_Priority)(meshtastic_MeshPacket_Priority_MAX+1))
|
||||
|
||||
Reference in New Issue
Block a user