From 3b8ea70d3c6e9b0fef324eb80f0e6722d83e6778b3718593f55caa641e5909a1 Mon Sep 17 00:00:00 2001 From: AidarKC Date: Sat, 13 Jun 2026 13:09:32 +0400 Subject: [PATCH] =?UTF-8?q?ESP32:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=B4=D0=B8=D0=B0=D0=B3=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B8=D0=BA=D1=83=20=D0=BF=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20SHiNE=20=D0=B8=20=D0=BF=D0=BE=D1=87?= =?UTF-8?q?=D0=B8=D0=BD=D0=B8=D1=82=D1=8C=20WS=20handshake?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...-06-13_1545_esp32_homeserver_pda_update.md | 1 - .../shine_homeserver_main.ino | 124 +++++++++++------- VERSION.properties | 4 +- 3 files changed, 76 insertions(+), 53 deletions(-) diff --git a/Dev_Docs/Pending_Features/2026-06-13_1545_esp32_homeserver_pda_update.md b/Dev_Docs/Pending_Features/2026-06-13_1545_esp32_homeserver_pda_update.md index 1d4068f..b007af3 100644 --- a/Dev_Docs/Pending_Features/2026-06-13_1545_esp32_homeserver_pda_update.md +++ b/Dev_Docs/Pending_Features/2026-06-13_1545_esp32_homeserver_pda_update.md @@ -16,7 +16,6 @@ 6. Если действие завершается ошибкой, проверить, что: - текст ошибки показан на экране результата; - команда `last_error` по USB возвращает полный сохранённый payload. - 7. Во временной диагностической сборке после старта устройства подождать 15 секунд и проверить, что при наличии жёлтой homeserver-кнопки устройство само делает попытку `ADD/FIX HOMESERVER`, а результат пишет в USB-диагностику. - ожидаемый результат: устройство после обычной регистрации пользователя способно отдельной транзакцией добавить или исправить homeserver-сессию в `shine_users` PDA, а ошибки этого шага сохраняются в ту же USB/NVS-диагностику. diff --git a/ESP32/esp32/ESP32-S3-Touch-AMOLED-2.16/main-device/shine_homeserver_main/shine_homeserver_main.ino b/ESP32/esp32/ESP32-S3-Touch-AMOLED-2.16/main-device/shine_homeserver_main/shine_homeserver_main.ino index a2c5aa8..48791dd 100644 --- a/ESP32/esp32/ESP32-S3-Touch-AMOLED-2.16/main-device/shine_homeserver_main/shine_homeserver_main.ino +++ b/ESP32/esp32/ESP32-S3-Touch-AMOLED-2.16/main-device/shine_homeserver_main/shine_homeserver_main.ino @@ -304,10 +304,6 @@ static String gLastRegisterDiagSummary; static String gLastRegisterDiagDetails; static String gLastRegisterDiagTime; static String gRegisterTriggerSource = "manual"; -static unsigned long gBootMillis = 0; -static bool gAutoHomeserverTestArmed = true; -static bool gAutoHomeserverTestStarted = false; -static unsigned long gLastAutoHomeserverAttemptMs = 0; static String gSerialCommandBuffer; static String gShineSessionId; static String gShineSessionKey; @@ -498,6 +494,7 @@ static bool readShineUserPda(const String &login, ShinePdaUserState &outState, S static bool parseShineUserPdaBytes(const std::vector &bytes, ShinePdaUserState &outState, String &errorOut); static void refreshAccountPdaStatus(); static void manageAccountPdaRefresh(); +static void saveShineConnectDiag(const String &status, const String &summary, const String &details); static bool ensureWebSocketConnected(SimpleWebSocketClient &ws, const String &url, String &errorOut); static void closeWebSocket(SimpleWebSocketClient &ws); static bool wsSendText(SimpleWebSocketClient &ws, const String &payload); @@ -2921,7 +2918,7 @@ static bool ensureWebSocketConnected(SimpleWebSocketClient &ws, const String &ur } ws.client.setInsecure(); - ws.client.setTimeout(5); + ws.client.setTimeout(5000); if (!ws.client.connect(ws.host.c_str(), ws.port)) { errorOut = "WS connect failed"; return false; @@ -2944,7 +2941,7 @@ static bool ensureWebSocketConnected(SimpleWebSocketClient &ws, const String &ur String statusLine = ws.client.readStringUntil('\n'); if (statusLine.indexOf("101") < 0) { - errorOut = "WS handshake failed"; + errorOut = String("WS handshake failed: ") + statusLine; closeWebSocket(ws); return false; } @@ -3100,41 +3097,58 @@ static bool shineWsRequest(SimpleWebSocketClient &ws, const String &op, const St static bool ensureShineSessionAuthenticated(String &errorOut) { errorOut = ""; + String diagDetails; + auto failWithDiag = [&](const String &summary) -> bool { + errorOut = summary; + saveShineConnectDiag("error", summary, diagDetails); + printRegisterDiagToSerial(); + return false; + }; + diagDetails += "kind=shine_connect\n"; + diagDetails += String("uptime_ms=") + String(millis()) + "\n"; + diagDetails += String("login=") + gLoginValue + "\n"; + diagDetails += String("homeserver=") + gHomeserverValue + "\n"; + diagDetails += String("server_url=") + gShineServerUrl + "\n"; + diagDetails += String("ws_url=") + shineWsUrl() + "\n"; + diagDetails += String("pda_status=") + gAccountPdaStatusMessage + "\n"; if (WiFi.status() != WL_CONNECTED) { - errorOut = "Wi-Fi disconnected"; - return false; + diagDetails += "wifi=disconnected\n"; + return failWithDiag("Wi-Fi disconnected"); } + diagDetails += String("wifi=connected:") + WiFi.localIP().toString() + "\n"; if (gLoginValue.isEmpty() || !gSecretConfigured || gHomeserverValue.isEmpty()) { - errorOut = "account not configured"; - return false; + return failWithDiag("account not configured"); } if (gAccountPdaStatus != ACCOUNT_PDA_OK) { - errorOut = "account not ready"; - return false; + return failWithDiag("account not ready"); } String wsUrl = shineWsUrl(); if (wsUrl.isEmpty()) { - errorOut = "shine server not set"; - return false; + return failWithDiag("shine server not set"); } if (!ensureWebSocketConnected(gShineWs, wsUrl, errorOut)) { - return false; + diagDetails += String("ws_connect_error=") + errorOut + "\n"; + return failWithDiag(errorOut.isEmpty() ? "WS connect failed" : errorOut); } + diagDetails += "ws_connected=true\n"; { String pingResp; if (!shineWsRequest(gShineWs, "Ping", "{\"ts\":0}", pingResp, SHINE_RPC_TIMEOUT_MS)) { - errorOut = "Ping failed"; - return false; + diagDetails += "ping_error=request_failed\n"; + return failWithDiag("Ping failed"); } + diagDetails += "ping_response<<\n"; + diagDetails += pingResp; + diagDetails += "\n>>ping_response\n"; uint64_t pingStatus = 0; uint64_t serverTs = 0; if (!jsonInt64Field(pingResp, "status", pingStatus) || pingStatus != 200 || !jsonInt64Field(pingResp, "ts", serverTs)) { - errorOut = "Ping rejected"; - return false; + return failWithDiag("Ping rejected"); } gShineServerTimeOffsetMs = (int64_t)serverTs - (int64_t)millis(); + diagDetails += String("server_time_offset_ms=") + String((long long)gShineServerTimeOffsetMs) + "\n"; } uint8_t deviceSeed[32] = {}; @@ -3145,21 +3159,26 @@ static bool ensureShineSessionAuthenticated(String &errorOut) { uint8_t subSec[64] = {}; if (!deriveSeedKeypairFromBase58(gDevicePrivB58, deviceSeed, devicePub, deviceSec) || !deriveSeedKeypairFromBase58(gHomeserverPrivB58, subSeed, subPub, subSec)) { - errorOut = "local key derive failed"; - return false; + return failWithDiag("local key derive failed"); } String sessionKey = buildSessionKeyStringFromPublicBase64(bytesToBase64String(subPub, 32)); + diagDetails += String("session_key=") + sessionKey + "\n"; if (!gShineSessionKey.isEmpty() && gShineSessionKey != sessionKey) { clearShineSessionState(true); + diagDetails += "stored_session_key_reset=true\n"; } if (!gShineSessionId.isEmpty()) { + diagDetails += String("stored_session_id=") + gShineSessionId + "\n"; String response; if (shineWsRequest(gShineWs, "SessionChallenge", String("{\"sessionId\":\"") + jsonEscape(gShineSessionId) + "\"}", response)) { + diagDetails += "session_challenge_response<<\n"; + diagDetails += response; + diagDetails += "\n>>session_challenge_response\n"; uint64_t statusCode = 0; String nonce; if (jsonInt64Field(response, "status", statusCode) && statusCode == 200 && jsonStringField(response, "nonce", nonce)) { @@ -3176,6 +3195,9 @@ static bool ensureShineSessionAuthenticated(String &errorOut) { + "\",\"clientInfo\":\"ESP32 homeserver\"}"; String loginResp; if (shineWsRequest(gShineWs, "SessionLogin", loginReq, loginResp)) { + diagDetails += "session_login_response<<\n"; + diagDetails += loginResp; + diagDetails += "\n>>session_login_response\n"; if (jsonInt64Field(loginResp, "status", statusCode) && statusCode == 200) { String storagePwd; if (jsonStringField(loginResp, "storagePwd", storagePwd)) { @@ -3184,6 +3206,7 @@ static bool ensureShineSessionAuthenticated(String &errorOut) { gShineSessionKey = sessionKey; gShineAuthenticated = true; saveShineSessionPrefs(); + saveShineConnectDiag("ok", "SessionLogin success", diagDetails); return true; } } @@ -3191,8 +3214,10 @@ static bool ensureShineSessionAuthenticated(String &errorOut) { } clearShineSessionState(true); if (!ensureWebSocketConnected(gShineWs, wsUrl, errorOut)) { - return false; + diagDetails += String("ws_reconnect_error=") + errorOut + "\n"; + return failWithDiag(errorOut.isEmpty() ? "WS reconnect failed" : errorOut); } + diagDetails += "stored_session_login_failed=true\n"; } if (gShineStoragePwd.isEmpty()) { @@ -3207,14 +3232,16 @@ static bool ensureShineSessionAuthenticated(String &errorOut) { if (!shineWsRequest(gShineWs, "AuthChallenge", String("{\"login\":\"") + jsonEscape(gLoginValue) + "\"}", authResp)) { - errorOut = "AuthChallenge failed"; - return false; + diagDetails += "auth_challenge_error=request_failed\n"; + return failWithDiag("AuthChallenge failed"); } + diagDetails += "auth_challenge_response<<\n"; + diagDetails += authResp; + diagDetails += "\n>>auth_challenge_response\n"; uint64_t statusCode = 0; String authNonce; if (!jsonInt64Field(authResp, "status", statusCode) || statusCode != 200 || !jsonStringField(authResp, "authNonce", authNonce)) { - errorOut = "AuthChallenge rejected"; - return false; + return failWithDiag("AuthChallenge rejected"); } uint64_t timeMs = shineNowMs(); @@ -3233,17 +3260,21 @@ static bool ensureShineSessionAuthenticated(String &errorOut) { + "\",\"clientInfo\":\"ESP32 homeserver\"}"; String createResp; if (!shineWsRequest(gShineWs, "CreateAuthSession", createReq, createResp)) { - errorOut = "CreateAuthSession failed"; - return false; + diagDetails += "create_auth_session_error=request_failed\n"; + return failWithDiag("CreateAuthSession failed"); } + diagDetails += "create_auth_session_response<<\n"; + diagDetails += createResp; + diagDetails += "\n>>create_auth_session_response\n"; if (!jsonInt64Field(createResp, "status", statusCode) || statusCode != 200 || !jsonStringField(createResp, "sessionId", gShineSessionId)) { - errorOut = "CreateAuthSession rejected"; - return false; + return failWithDiag("CreateAuthSession rejected"); } gShineSessionKey = sessionKey; gShineAuthenticated = true; saveShineSessionPrefs(); + diagDetails += String("new_session_id=") + gShineSessionId + "\n"; + saveShineConnectDiag("ok", "CreateAuthSession success", diagDetails); return true; } @@ -3292,6 +3323,15 @@ static void manageShineConnection() { return; } } + String details; + details += "kind=shine_ping\n"; + details += String("uptime_ms=") + String(millis()) + "\n"; + details += String("server_url=") + gShineServerUrl + "\n"; + details += "ping_response<<\n"; + details += pingResp; + details += "\n>>ping_response\n"; + saveShineConnectDiag("error", "Ping keepalive failed", details); + printRegisterDiagToSerial(); gShineStatusLine = String("SHiNE: ") + serverLabel + " unavailable"; clearShineSessionState(false); } @@ -3562,6 +3602,10 @@ static void clearRegisterDiag() { clearRegisterDiagDetailsFromPrefs(); } +static void saveShineConnectDiag(const String &status, const String &summary, const String &details) { + saveRegisterDiag(status, summary, details); +} + static void printRegisterDiagToSerial() { Serial.println("LAST_REGISTER_DIAG_BEGIN"); Serial.println(String("status=") + gLastRegisterDiagStatus); @@ -5053,7 +5097,6 @@ static void handleSwipe(SwipeDirection swipe) { void setup() { Serial.begin(115200); sodium_init(); - gBootMillis = millis(); Wire.begin(PIN_I2C_SDA, PIN_I2C_SCL); initPowerManagement(); @@ -5115,25 +5158,6 @@ void loop() { manageAccountPdaRefresh(); manageShineConnection(); - if (gAutoHomeserverTestArmed - && !gTouchDown - && millis() - gBootMillis >= 15000UL - && millis() - gLastAutoHomeserverAttemptMs >= 45000UL - && gShowHomeserverPdaActionButton - && (gHomeserverPdaCanAdd || gHomeserverPdaCanFix)) { - gAutoHomeserverTestStarted = true; - gLastAutoHomeserverAttemptMs = millis(); - gRegisterTriggerSource = gHomeserverPdaCanFix ? "auto-boot-fix-homeserver" : "auto-boot-add-homeserver"; - String updateMessage; - Serial.println("AUTO_HOMESERVER_PDA_BEGIN"); - if (!updateHomeserverSessionOnSolana(gHomeserverPdaCanFix, updateMessage)) { - gHomeserverPdaResultSuccess = false; - gHomeserverPdaResultMessage = updateMessage; - gHomeserverPdaResultDetails = ""; - } - Serial.println("AUTO_HOMESERVER_PDA_END"); - } - static unsigned long lastHomeRefreshMs = 0; if (gCurrentScreen == SCREEN_HOME && !gTouchDown && millis() - lastHomeRefreshMs >= HOME_REFRESH_MS) { lastHomeRefreshMs = millis(); diff --git a/VERSION.properties b/VERSION.properties index 18a6233..523bb02 100644 --- a/VERSION.properties +++ b/VERSION.properties @@ -1,2 +1,2 @@ -client.version=1.2.177 -server.version=1.2.166 +client.version=1.2.179 +server.version=1.2.168