Add low memory warning (#417)

This commit is contained in:
Ken Van Hoeylandt
2025-11-14 15:43:00 +01:00
committed by GitHub
parent dddca1ea76
commit a4f4784ed9
7 changed files with 145 additions and 4 deletions
+2
View File
@@ -43,6 +43,7 @@ namespace service {
// Secondary (UI)
namespace gui { extern const ServiceManifest manifest; }
namespace loader { extern const ServiceManifest manifest; }
namespace memorychecker { extern const ServiceManifest manifest; }
namespace statusbar { extern const ServiceManifest manifest; }
#if TT_FEATURE_SCREENSHOT_ENABLED
namespace screenshot { extern const ServiceManifest manifest; }
@@ -215,6 +216,7 @@ static void registerAndStartSecondaryServices() {
addService(service::loader::manifest);
addService(service::gui::manifest);
addService(service::statusbar::manifest);
addService(service::memorychecker::manifest);
#if TT_FEATURE_SCREENSHOT_ENABLED
addService(service::screenshot::manifest);
#endif
+3 -3
View File
@@ -229,13 +229,13 @@ static void statusbar_event(TT_UNUSED const lv_obj_class_t* class_p, lv_event_t*
}
}
int8_t statusbar_icon_add(const std::string& image) {
int8_t statusbar_icon_add(const std::string& image, bool visible) {
statusbar_data.mutex.lock();
int8_t result = -1;
for (int8_t i = 0; i < STATUSBAR_ICON_LIMIT; ++i) {
if (!statusbar_data.icons[i].claimed) {
statusbar_data.icons[i].claimed = true;
statusbar_data.icons[i].visible = !image.empty();
statusbar_data.icons[i].visible = visible;
statusbar_data.icons[i].image = image;
result = i;
TT_LOG_D(TAG, "id %d: added", i);
@@ -248,7 +248,7 @@ int8_t statusbar_icon_add(const std::string& image) {
}
int8_t statusbar_icon_add() {
return statusbar_icon_add("");
return statusbar_icon_add("", false);
}
void statusbar_icon_remove(int8_t id) {
@@ -0,0 +1,93 @@
#include <Tactility/Tactility.h>
#include <Tactility/lvgl/Statusbar.h>
#include <Tactility/service/ServiceContext.h>
#include <Tactility/service/ServiceManifest.h>
#include <Tactility/service/ServicePaths.h>
#include <Tactility/service/memorychecker/MemoryCheckerService.h>
namespace tt::service::memorychecker {
constexpr const char* TAG = "MemoryChecker";
constexpr TickType_t TIMER_UPDATE_INTERVAL = 1000U / portTICK_PERIOD_MS;
// Total memory (in bytes) that should be free before warnings occur
constexpr auto TOTAL_FREE_THRESHOLD = 10'000;
// Smallest memory block size (in bytes) that should be available before warnings occur
constexpr auto LARGEST_FREE_BLOCK_THRESHOLD = 2'000;
static size_t getInternalFree() {
#ifdef ESP_PLATFORM
return heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
#else
// PC mock data
return 1024 * 1024;
#endif
}
static size_t getInternalLargestFreeBlock() {
#ifdef ESP_PLATFORM
return heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL);
#else
// PC mock data
return 1024 * 1024;
#endif
}
static bool isMemoryLow() {
bool memory_low = false;
const auto total_free = getInternalFree();
if (total_free < TOTAL_FREE_THRESHOLD) {
TT_LOG_W(TAG, "Internal memory low: %zu bytes", total_free);
memory_low = true;
}
const auto largest_block = getInternalLargestFreeBlock();
if (largest_block < LARGEST_FREE_BLOCK_THRESHOLD) {
TT_LOG_W(TAG, "Largest free internal memory block is %zu bytes", largest_block);
memory_low = true;
}
return memory_low;
}
bool MemoryCheckerService::onStart(ServiceContext& service) {
auto lock = mutex.asScopedLock();
lock.lock();
auto icon_path = std::string("A:") + service.getPaths()->getAssetsPath("memory_alert.png");
statusbarIconId = lvgl::statusbar_icon_add(icon_path, false);
lvgl::statusbar_icon_set_visibility(statusbarIconId, false);
timer.setThreadPriority(Thread::Priority::Lower);
timer.start(TIMER_UPDATE_INTERVAL);
return true;
}
void MemoryCheckerService::onStop(ServiceContext& service) {
timer.stop();
// Lock after timer stop, because the timer task might still be busy and this way we await it
auto lock = mutex.asScopedLock();
lock.lock();
lvgl::statusbar_icon_remove(statusbarIconId);
}
void MemoryCheckerService::onTimerUpdate() {
auto lock = mutex.asScopedLock();
lock.lock();
bool memory_low = isMemoryLow();
if (memory_low != memoryLow) {
memoryLow = memory_low;
lvgl::statusbar_icon_set_visibility(statusbarIconId, memory_low);
}
}
extern const ServiceManifest manifest = {
.id = "MemoryChecker",
.createService = create<MemoryCheckerService>
};
}
@@ -269,6 +269,8 @@ public:
service->update();
});
updateTimer->setThreadPriority(Thread::Priority::Lower);
// We want to try and scan more often in case of startup or scan lock failure
updateTimer->start(1000);