ESP32: смягчить SHiNE reconnect при плохом сервере

This commit is contained in:
AidarKC 2026-06-14 11:01:47 +04:00
parent 423d490939
commit 05492306c0
3 changed files with 66 additions and 6 deletions

View File

@ -0,0 +1,26 @@
# ESP32 антифриз при неверном SHiNE server
- Статус: `pending`
## Что сделано
- уменьшены таймауты `SHiNE`-запросов и `WS`-подключения;
- повторные попытки подключения переведены на backoff:
- `10s`
- `20s`
- максимум `30s`
- пока открыт экран настроек или редактирования, новые фоновые попытки `SHiNE reconnect` не запускаются.
## Что проверять
1. Указать неверный адрес `SHiNE server`.
2. Дождаться статуса `unavailable`.
3. Проверить, что `HOME` не подвисает на секунды.
4. Проверить, что можно открыть `SETTINGS -> Server` и исправить адрес без лагов.
5. После сохранения правильного адреса убедиться, что reconnect снова идёт и устройство подключается.
## Ожидаемый результат
- при неверном адресе UI остаётся управляемым;
- вход в настройки и редактирование сервера остаются быстрыми;
- после исправления адреса устройство снова подключается без долгой паузы.

View File

@ -57,8 +57,10 @@ int ge25519_frombytes(ge25519_p3 *h, const unsigned char *s);
#define HOME_REFRESH_MS 1000
#define ACCOUNT_CHECK_RETRY_MS 15000
#define SHINE_PING_INTERVAL_MS 60000
#define SHINE_RECONNECT_MS 10000
#define SHINE_RPC_TIMEOUT_MS 9000
#define SHINE_RECONNECT_MIN_MS 10000
#define SHINE_RECONNECT_MAX_MS 30000
#define SHINE_RPC_TIMEOUT_MS 2500
#define SHINE_WS_CONNECT_TIMEOUT_MS 1500
#define TEXT_EDIT_PANEL_X 10
#define TEXT_EDIT_PANEL_Y 112
#define TEXT_EDIT_PANEL_W 460
@ -322,6 +324,7 @@ static String gShineStoragePwd;
static bool gShineAuthenticated = false;
static unsigned long gLastShineAttemptMs = 0;
static unsigned long gLastShinePingMs = 0;
static unsigned long gShineReconnectDelayMs = SHINE_RECONNECT_MIN_MS;
static uint32_t gWsRequestCounter = 1;
static int64_t gShineServerTimeOffsetMs = 0;
static SimpleWebSocketClient gShineWs;
@ -975,6 +978,25 @@ static void clearShineSessionState(bool clearStoredSession) {
}
}
static bool shouldPauseShineReconnectForUi() {
switch (gCurrentScreen) {
case SCREEN_SETTINGS_MENU:
case SCREEN_WIFI:
case SCREEN_SERVER:
case SCREEN_ACCOUNT:
case SCREEN_ACCOUNT_HOMESERVER:
case SCREEN_ACCOUNT_SECRET:
case SCREEN_SECRET_SHOW:
case SCREEN_SECRET_GENERATE_INFO:
case SCREEN_SECRET_GENERATE_RUNNING:
case SCREEN_SECRET_GENERATE_CANCEL_CONFIRM:
case SCREEN_TEXT_EDIT:
return true;
default:
return false;
}
}
static void markAccountStateDirty() {
gAccountCheckPending = true;
gLastAccountCheckMs = 0;
@ -2978,7 +3000,7 @@ static bool ensureWebSocketConnected(SimpleWebSocketClient &ws, const String &ur
}
ws.client.setInsecure();
ws.client.setTimeout(5000);
ws.client.setTimeout(SHINE_WS_CONNECT_TIMEOUT_MS);
if (!ws.client.connect(ws.host.c_str(), ws.port)) {
errorOut = "WS connect failed";
return false;
@ -3347,22 +3369,28 @@ static void manageShineConnection() {
if (gLoginValue.isEmpty() || !gSecretConfigured || gHomeserverValue.isEmpty()) {
gShineStatusLine = String("SHiNE: ") + serverLabel + " account not configured";
clearShineSessionState(false);
gShineReconnectDelayMs = SHINE_RECONNECT_MIN_MS;
return;
}
if (gAccountPdaStatus != ACCOUNT_PDA_OK) {
gShineStatusLine = String("SHiNE: ") + serverLabel + " account not configured";
clearShineSessionState(false);
gShineReconnectDelayMs = SHINE_RECONNECT_MIN_MS;
return;
}
if (WiFi.status() != WL_CONNECTED) {
gShineStatusLine = String("SHiNE: ") + serverLabel + " unavailable";
clearShineSessionState(false);
gShineReconnectDelayMs = SHINE_RECONNECT_MIN_MS;
return;
}
unsigned long now = millis();
if (!gShineAuthenticated || !gShineWs.connected || !gShineWs.client.connected()) {
if (now - gLastShineAttemptMs < SHINE_RECONNECT_MS) {
if (shouldPauseShineReconnectForUi()) {
return;
}
if (now - gLastShineAttemptMs < gShineReconnectDelayMs) {
return;
}
gLastShineAttemptMs = now;
@ -3370,9 +3398,11 @@ static void manageShineConnection() {
if (ensureShineSessionAuthenticated(error)) {
gShineStatusLine = String("SHiNE: ") + serverLabel + " connected";
gLastShinePingMs = now;
gShineReconnectDelayMs = SHINE_RECONNECT_MIN_MS;
} else {
gShineStatusLine = String("SHiNE: ") + serverLabel + " unavailable";
clearShineSessionState(false);
gShineReconnectDelayMs = min(gShineReconnectDelayMs + SHINE_RECONNECT_MIN_MS, (unsigned long)SHINE_RECONNECT_MAX_MS);
}
return;
}
@ -3383,6 +3413,7 @@ static void manageShineConnection() {
uint64_t statusCode = 0;
if (jsonInt64Field(pingResp, "status", statusCode) && statusCode == 200) {
gLastShinePingMs = now;
gShineReconnectDelayMs = SHINE_RECONNECT_MIN_MS;
gShineStatusLine = String("SHiNE: ") + serverLabel + " connected";
return;
}
@ -3398,6 +3429,7 @@ static void manageShineConnection() {
printRegisterDiagToSerial();
gShineStatusLine = String("SHiNE: ") + serverLabel + " unavailable";
clearShineSessionState(false);
gShineReconnectDelayMs = min(gShineReconnectDelayMs + SHINE_RECONNECT_MIN_MS, (unsigned long)SHINE_RECONNECT_MAX_MS);
}
}
@ -4012,6 +4044,8 @@ static void applyEditorValue() {
saveServerPrefs();
gServerStatusMessage = "Shine server saved";
clearShineSessionState(false);
gShineReconnectDelayMs = SHINE_RECONNECT_MIN_MS;
gLastShineAttemptMs = 0;
gShineStatusLine = "SHiNE: reconnect pending";
showScreen(SCREEN_SERVER);
return;

View File

@ -1,2 +1,2 @@
client.version=1.2.187
server.version=1.2.176
client.version=1.2.188
server.version=1.2.177