Split menu actions for smaller footprint

This commit is contained in:
jpirnay
2026-04-07 21:39:03 +02:00
parent abbf69649e
commit 6dd905fb5a
9 changed files with 255 additions and 50 deletions
+3
View File
@@ -302,6 +302,8 @@ STR_HW_RIGHT_LABEL: "Right (4th button)"
STR_GO_TO_PERCENT: "Go to %"
STR_GO_HOME_BUTTON: "Go Home"
STR_SYNC_PROGRESS: "Sync Progress"
STR_PUSH_PROGRESS_FROM_THIS_DEVICE: "Push progress from this device"
STR_PULL_PROGRESS_FROM_OTHER_DEVICES: "Pull progress from other devices"
STR_DELETE_CACHE: "Delete Book Cache"
STR_DELETE: "Delete"
STR_REMOVE: "Remove"
@@ -331,6 +333,7 @@ STR_UPLOAD_LOCAL: "Upload local progress"
STR_NO_REMOTE_MSG: "No remote progress found"
STR_UPLOAD_PROMPT: "Upload current position?"
STR_UPLOAD_SUCCESS: "Progress uploaded!"
STR_PULL_SUCCESS: "Remote progress applied!"
STR_SYNC_FAILED_MSG: "Sync failed"
STR_SECTION_PREFIX: "Section "
STR_UPLOAD: "Upload"
+59 -9
View File
@@ -11,8 +11,8 @@
#include <algorithm>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <ctime>
#include "KOReaderCredentialStore.h"
@@ -50,7 +50,9 @@ constexpr char DEVICE_ID[] = "crosspoint-reader";
// Payloads are tiny JSON, so throughput impact is minimal while avoiding
// large transient allocations from default client buffer sizes.
constexpr int HTTP_BUF_SIZE = 1024;
constexpr unsigned TLS_CONTIG_HEAP_TOLERANCE = 512;
// Keep strict thresholding here. A small tolerance caused repeated handshake
// attempts in borderline-fragmented states that still failed in mbedTLS.
constexpr unsigned TLS_CONTIG_HEAP_TOLERANCE = 0;
// Captures radio/link state around failed connects.
// Why: many field failures look like TLS errors but are actually weak WiFi.
@@ -135,10 +137,9 @@ std::string base64Encode(const std::string& input) {
// lastFailureDetail() will report the heap shortage instead of attempting a doomed handshake.
bool checkHeapForTls() {
const bool hasReusableSession = g_keepSessionOpen && g_sessionClient != nullptr;
const bool isUpload = (KOReaderSyncClient::lastOperation &&
strcmp(KOReaderSyncClient::lastOperation, "update progress") == 0);
const unsigned requiredContig =
isUpload ? KOReaderSyncClient::MIN_CONTIG_HEAP_FOR_TLS_UPLOAD : KOReaderSyncClient::MIN_CONTIG_HEAP_FOR_TLS;
const bool isUpload =
(KOReaderSyncClient::lastOperation && strcmp(KOReaderSyncClient::lastOperation, "update progress") == 0);
const unsigned requiredContig = KOReaderSyncClient::MIN_CONTIG_HEAP_FOR_TLS;
// Upload can often reuse the already-established GET connection. In that case
// a full handshake allocation is typically unnecessary, so avoid failing fast
@@ -158,6 +159,30 @@ bool checkHeapForTls() {
return true;
}
void refreshHeapSnapshot() {
KOReaderSyncClient::lastHeapAtFailure = ESP.getFreeHeap();
KOReaderSyncClient::lastContigHeapAtFailure = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_DEFAULT);
}
void logTlsAttemptPlan(const char* operation, int attempt) {
const bool isUpload = (operation && strcmp(operation, "update progress") == 0);
const bool hasReusableSession = g_keepSessionOpen && g_sessionClient != nullptr;
const unsigned requiredContig = (isUpload && hasReusableSession) ? KOReaderSyncClient::MIN_CONTIG_HEAP_FOR_TLS_UPLOAD
: KOReaderSyncClient::MIN_CONTIG_HEAP_FOR_TLS;
LOG_DBG("KOSync", "%s attempt %d: keep_session=%s reusable_session=%s tls_mode=%s heap=%u contig=%u need=%u",
operation ? operation : "request", attempt, g_keepSessionOpen ? "yes" : "no",
hasReusableSession ? "yes" : "no", (isUpload && hasReusableSession) ? "reuse" : "handshake",
KOReaderSyncClient::lastHeapAtFailure, KOReaderSyncClient::lastContigHeapAtFailure, requiredContig);
}
void resetSessionClientForRetry() {
if (g_sessionClient) {
esp_http_client_cleanup(g_sessionClient);
g_sessionClient = nullptr;
}
}
// Create configured esp_http_client with small TLS buffers
esp_http_client_handle_t createClient(const char* url, ResponseBuffer* buf,
esp_http_client_method_t method = HTTP_METHOD_GET) {
@@ -352,6 +377,14 @@ KOReaderSyncClient::Error KOReaderSyncClient::getProgress(const std::string& doc
int httpCode = 0;
for (int attempt = 1; attempt <= 2; attempt++) {
// Retry attempts can happen after memory churn from a failed handshake.
// Refresh heap snapshot each pass so preflight and diagnostics use current values.
refreshHeapSnapshot();
logTlsAttemptPlan("get progress", attempt);
if (!checkHeapForTls()) {
return NETWORK_ERROR;
}
clearResponseBuffer(activeBuf);
esp_http_client_handle_t client = createClient(url.c_str(), &buf);
@@ -378,6 +411,10 @@ KOReaderSyncClient::Error KOReaderSyncClient::getProgress(const std::string& doc
break;
}
// Failed connect can leave a persistent client handle in a bad state.
// Recreate it before retry so we don't repeat work on a stale transport.
resetSessionClientForRetry();
LOG_ERR("KOSync", "getProgress connect failed on attempt %d, retrying once", attempt);
logWifiSnapshot("WiFi before getProgress retry");
delay(400);
@@ -442,6 +479,14 @@ KOReaderSyncClient::Error KOReaderSyncClient::updateProgress(const KOReaderProgr
int httpCode = 0;
for (int attempt = 1; attempt <= 2; attempt++) {
// Retry attempts can happen after memory churn from a failed handshake.
// Refresh heap snapshot each pass so preflight and diagnostics use current values.
refreshHeapSnapshot();
logTlsAttemptPlan("update progress", attempt);
if (!checkHeapForTls()) {
return NETWORK_ERROR;
}
clearResponseBuffer(activeBuf);
esp_http_client_handle_t client = createClient(url.c_str(), &buf, HTTP_METHOD_PUT);
@@ -462,8 +507,7 @@ KOReaderSyncClient::Error KOReaderSyncClient::updateProgress(const KOReaderProgr
esp_http_client_cleanup(client);
}
LOG_DBG("KOSync", "Update progress response: %d (err: %s) [attempt %d]", httpCode, esp_err_to_name(err),
attempt);
LOG_DBG("KOSync", "Update progress response: %d (err: %s) [attempt %d]", httpCode, esp_err_to_name(err), attempt);
// Retry exactly once for connect-level failures only.
// Why: same policy as GET keeps behavior predictable across both endpoints.
@@ -471,6 +515,10 @@ KOReaderSyncClient::Error KOReaderSyncClient::updateProgress(const KOReaderProgr
break;
}
// Failed connect can leave a persistent client handle in a bad state.
// Recreate it before retry so we don't repeat work on a stale transport.
resetSessionClientForRetry();
LOG_ERR("KOSync", "updateProgress connect failed on attempt %d, retrying once", attempt);
logWifiSnapshot("WiFi before updateProgress retry");
delay(400);
@@ -484,7 +532,9 @@ KOReaderSyncClient::Error KOReaderSyncClient::updateProgress(const KOReaderProgr
const char* KOReaderSyncClient::lastFailureDetail() {
const bool isUpload = (lastOperation && strcmp(lastOperation, "update progress") == 0);
const unsigned requiredContig = isUpload ? MIN_CONTIG_HEAP_FOR_TLS_UPLOAD : MIN_CONTIG_HEAP_FOR_TLS;
const bool hasReusableSession = g_keepSessionOpen && g_sessionClient != nullptr;
const unsigned requiredContig =
(isUpload && hasReusableSession) ? MIN_CONTIG_HEAP_FOR_TLS_UPLOAD : MIN_CONTIG_HEAP_FOR_TLS;
// Heap-pressure case: surfaced when checkHeapForTls() refused before any TCP/TLS work happened.
if (lastEspError == ESP_ERR_NO_MEM && lastHttpCode == 0) {
+2
View File
@@ -112,5 +112,7 @@ class KOReaderSyncClient {
* reports a heap-pressure message instead of attempting (and crashing) the TLS handshake.
*/
static constexpr unsigned MIN_CONTIG_HEAP_FOR_TLS = 36 * 1024;
// Relaxed threshold only for upload when reusing an already-established session.
// Uploads that must perform a fresh handshake still require MIN_CONTIG_HEAP_FOR_TLS.
static constexpr unsigned MIN_CONTIG_HEAP_FOR_TLS_UPLOAD = 34 * 1024;
};